geode-rng.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /*
  2. * RNG driver for AMD Geode RNGs
  3. *
  4. * Copyright 2005 (c) MontaVista Software, Inc.
  5. *
  6. * with the majority of the code coming from:
  7. *
  8. * Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
  9. * (c) Copyright 2003 Red Hat Inc <[email protected]>
  10. *
  11. * derived from
  12. *
  13. * Hardware driver for the AMD 768 Random Number Generator (RNG)
  14. * (c) Copyright 2001 Red Hat Inc
  15. *
  16. * derived from
  17. *
  18. * Hardware driver for Intel i810 Random Number Generator (RNG)
  19. * Copyright 2000,2001 Jeff Garzik <[email protected]>
  20. * Copyright 2000,2001 Philipp Rumpf <[email protected]>
  21. *
  22. * This file is licensed under the terms of the GNU General Public
  23. * License version 2. This program is licensed "as is" without any
  24. * warranty of any kind, whether express or implied.
  25. */
  26. #include <linux/delay.h>
  27. #include <linux/hw_random.h>
  28. #include <linux/io.h>
  29. #include <linux/kernel.h>
  30. #include <linux/module.h>
  31. #include <linux/pci.h>
  32. #define PFX KBUILD_MODNAME ": "
  33. #define GEODE_RNG_DATA_REG 0x50
  34. #define GEODE_RNG_STATUS_REG 0x54
  35. /*
  36. * Data for PCI driver interface
  37. *
  38. * This data only exists for exporting the supported
  39. * PCI ids via MODULE_DEVICE_TABLE. We do not actually
  40. * register a pci_driver, because someone else might one day
  41. * want to register another driver on the same PCI id.
  42. */
  43. static const struct pci_device_id pci_tbl[] = {
  44. { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_LX_AES), 0, },
  45. { 0, }, /* terminate list */
  46. };
  47. MODULE_DEVICE_TABLE(pci, pci_tbl);
  48. struct amd_geode_priv {
  49. struct pci_dev *pcidev;
  50. void __iomem *membase;
  51. };
  52. static int geode_rng_data_read(struct hwrng *rng, u32 *data)
  53. {
  54. struct amd_geode_priv *priv = (struct amd_geode_priv *)rng->priv;
  55. void __iomem *mem = priv->membase;
  56. *data = readl(mem + GEODE_RNG_DATA_REG);
  57. return 4;
  58. }
  59. static int geode_rng_data_present(struct hwrng *rng, int wait)
  60. {
  61. struct amd_geode_priv *priv = (struct amd_geode_priv *)rng->priv;
  62. void __iomem *mem = priv->membase;
  63. int data, i;
  64. for (i = 0; i < 20; i++) {
  65. data = !!(readl(mem + GEODE_RNG_STATUS_REG));
  66. if (data || !wait)
  67. break;
  68. udelay(10);
  69. }
  70. return data;
  71. }
  72. static struct hwrng geode_rng = {
  73. .name = "geode",
  74. .data_present = geode_rng_data_present,
  75. .data_read = geode_rng_data_read,
  76. };
  77. static int __init geode_rng_init(void)
  78. {
  79. int err = -ENODEV;
  80. struct pci_dev *pdev = NULL;
  81. const struct pci_device_id *ent;
  82. void __iomem *mem;
  83. unsigned long rng_base;
  84. struct amd_geode_priv *priv;
  85. for_each_pci_dev(pdev) {
  86. ent = pci_match_id(pci_tbl, pdev);
  87. if (ent)
  88. goto found;
  89. }
  90. /* Device not found. */
  91. return err;
  92. found:
  93. priv = kzalloc(sizeof(*priv), GFP_KERNEL);
  94. if (!priv) {
  95. err = -ENOMEM;
  96. goto put_dev;
  97. }
  98. rng_base = pci_resource_start(pdev, 0);
  99. if (rng_base == 0)
  100. goto free_priv;
  101. err = -ENOMEM;
  102. mem = ioremap(rng_base, 0x58);
  103. if (!mem)
  104. goto free_priv;
  105. geode_rng.priv = (unsigned long)priv;
  106. priv->membase = mem;
  107. priv->pcidev = pdev;
  108. pr_info("AMD Geode RNG detected\n");
  109. err = hwrng_register(&geode_rng);
  110. if (err) {
  111. pr_err(PFX "RNG registering failed (%d)\n",
  112. err);
  113. goto err_unmap;
  114. }
  115. return err;
  116. err_unmap:
  117. iounmap(mem);
  118. free_priv:
  119. kfree(priv);
  120. put_dev:
  121. pci_dev_put(pdev);
  122. return err;
  123. }
  124. static void __exit geode_rng_exit(void)
  125. {
  126. struct amd_geode_priv *priv;
  127. priv = (struct amd_geode_priv *)geode_rng.priv;
  128. hwrng_unregister(&geode_rng);
  129. iounmap(priv->membase);
  130. pci_dev_put(priv->pcidev);
  131. kfree(priv);
  132. }
  133. module_init(geode_rng_init);
  134. module_exit(geode_rng_exit);
  135. MODULE_DESCRIPTION("H/W RNG driver for AMD Geode LX CPUs");
  136. MODULE_LICENSE("GPL");