intel-rng.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. /*
  2. * RNG driver for Intel 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 <jgarzik@redhat.com>
  10. *
  11. * derived from
  12. *
  13. * Hardware driver for the AMD 768 Random Number Generator (RNG)
  14. * (c) Copyright 2001 Red Hat Inc <alan@redhat.com>
  15. *
  16. * derived from
  17. *
  18. * Hardware driver for Intel i810 Random Number Generator (RNG)
  19. * Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
  20. * Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
  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/module.h>
  27. #include <linux/kernel.h>
  28. #include <linux/pci.h>
  29. #include <linux/hw_random.h>
  30. #include <asm/io.h>
  31. #define PFX KBUILD_MODNAME ": "
  32. /*
  33. * RNG registers
  34. */
  35. #define INTEL_RNG_HW_STATUS 0
  36. #define INTEL_RNG_PRESENT 0x40
  37. #define INTEL_RNG_ENABLED 0x01
  38. #define INTEL_RNG_STATUS 1
  39. #define INTEL_RNG_DATA_PRESENT 0x01
  40. #define INTEL_RNG_DATA 2
  41. /*
  42. * Magic address at which Intel PCI bridges locate the RNG
  43. */
  44. #define INTEL_RNG_ADDR 0xFFBC015F
  45. #define INTEL_RNG_ADDR_LEN 3
  46. /*
  47. * LPC bridge PCI config space registers
  48. */
  49. #define FWH_DEC_EN1_REG_OLD 0xe3
  50. #define FWH_DEC_EN1_REG_NEW 0xd9 /* high byte of 16-bit register */
  51. #define FWH_F8_EN_MASK 0x80
  52. #define BIOS_CNTL_REG_OLD 0x4e
  53. #define BIOS_CNTL_REG_NEW 0xdc
  54. #define BIOS_CNTL_WRITE_ENABLE_MASK 0x01
  55. #define BIOS_CNTL_LOCK_ENABLE_MASK 0x02
  56. /*
  57. * Magic address at which Intel Firmware Hubs get accessed
  58. */
  59. #define INTEL_FWH_ADDR 0xffff0000
  60. #define INTEL_FWH_ADDR_LEN 2
  61. /*
  62. * Intel Firmware Hub command codes (write to any address inside the device)
  63. */
  64. #define INTEL_FWH_RESET_CMD 0xff /* aka READ_ARRAY */
  65. #define INTEL_FWH_READ_ID_CMD 0x90
  66. /*
  67. * Intel Firmware Hub Read ID command result addresses
  68. */
  69. #define INTEL_FWH_MANUFACTURER_CODE_ADDRESS 0x000000
  70. #define INTEL_FWH_DEVICE_CODE_ADDRESS 0x000001
  71. /*
  72. * Intel Firmware Hub Read ID command result values
  73. */
  74. #define INTEL_FWH_MANUFACTURER_CODE 0x89
  75. #define INTEL_FWH_DEVICE_CODE_8M 0xac
  76. #define INTEL_FWH_DEVICE_CODE_4M 0xad
  77. /*
  78. * Data for PCI driver interface
  79. *
  80. * This data only exists for exporting the supported
  81. * PCI ids via MODULE_DEVICE_TABLE. We do not actually
  82. * register a pci_driver, because someone else might one day
  83. * want to register another driver on the same PCI id.
  84. */
  85. static const struct pci_device_id pci_tbl[] = {
  86. /* AA
  87. { 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
  88. { 0x8086, 0x2410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* AA */
  89. /* AB
  90. { 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
  91. { 0x8086, 0x2420, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* AB */
  92. /* ??
  93. { 0x8086, 0x2430, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
  94. /* BAM, CAM, DBM, FBM, GxM
  95. { 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
  96. { 0x8086, 0x244c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* BAM */
  97. { 0x8086, 0x248c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CAM */
  98. { 0x8086, 0x24cc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* DBM */
  99. { 0x8086, 0x2641, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* FBM */
  100. { 0x8086, 0x27b9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* GxM */
  101. { 0x8086, 0x27bd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* GxM DH */
  102. /* BA, CA, DB, Ex, 6300, Fx, 631x/632x, Gx
  103. { 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
  104. { 0x8086, 0x2440, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* BA */
  105. { 0x8086, 0x2480, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CA */
  106. { 0x8086, 0x24c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* DB */
  107. { 0x8086, 0x24d0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Ex */
  108. { 0x8086, 0x25a1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 6300 */
  109. { 0x8086, 0x2640, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Fx */
  110. { 0x8086, 0x2670, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
  111. { 0x8086, 0x2671, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
  112. { 0x8086, 0x2672, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
  113. { 0x8086, 0x2673, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
  114. { 0x8086, 0x2674, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
  115. { 0x8086, 0x2675, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
  116. { 0x8086, 0x2676, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
  117. { 0x8086, 0x2677, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
  118. { 0x8086, 0x2678, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
  119. { 0x8086, 0x2679, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
  120. { 0x8086, 0x267a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
  121. { 0x8086, 0x267b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
  122. { 0x8086, 0x267c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
  123. { 0x8086, 0x267d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
  124. { 0x8086, 0x267e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
  125. { 0x8086, 0x267f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
  126. { 0x8086, 0x27b8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Gx */
  127. /* E
  128. { 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
  129. { 0x8086, 0x2450, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* E */
  130. { 0, }, /* terminate list */
  131. };
  132. MODULE_DEVICE_TABLE(pci, pci_tbl);
  133. static inline u8 hwstatus_get(void __iomem *mem)
  134. {
  135. return readb(mem + INTEL_RNG_HW_STATUS);
  136. }
  137. static inline u8 hwstatus_set(void __iomem *mem,
  138. u8 hw_status)
  139. {
  140. writeb(hw_status, mem + INTEL_RNG_HW_STATUS);
  141. return hwstatus_get(mem);
  142. }
  143. static int intel_rng_data_present(struct hwrng *rng)
  144. {
  145. void __iomem *mem = (void __iomem *)rng->priv;
  146. return !!(readb(mem + INTEL_RNG_STATUS) & INTEL_RNG_DATA_PRESENT);
  147. }
  148. static int intel_rng_data_read(struct hwrng *rng, u32 *data)
  149. {
  150. void __iomem *mem = (void __iomem *)rng->priv;
  151. *data = readb(mem + INTEL_RNG_DATA);
  152. return 1;
  153. }
  154. static int intel_rng_init(struct hwrng *rng)
  155. {
  156. void __iomem *mem = (void __iomem *)rng->priv;
  157. u8 hw_status;
  158. int err = -EIO;
  159. hw_status = hwstatus_get(mem);
  160. /* turn RNG h/w on, if it's off */
  161. if ((hw_status & INTEL_RNG_ENABLED) == 0)
  162. hw_status = hwstatus_set(mem, hw_status | INTEL_RNG_ENABLED);
  163. if ((hw_status & INTEL_RNG_ENABLED) == 0) {
  164. printk(KERN_ERR PFX "cannot enable RNG, aborting\n");
  165. goto out;
  166. }
  167. err = 0;
  168. out:
  169. return err;
  170. }
  171. static void intel_rng_cleanup(struct hwrng *rng)
  172. {
  173. void __iomem *mem = (void __iomem *)rng->priv;
  174. u8 hw_status;
  175. hw_status = hwstatus_get(mem);
  176. if (hw_status & INTEL_RNG_ENABLED)
  177. hwstatus_set(mem, hw_status & ~INTEL_RNG_ENABLED);
  178. else
  179. printk(KERN_WARNING PFX "unusual: RNG already disabled\n");
  180. }
  181. static struct hwrng intel_rng = {
  182. .name = "intel",
  183. .init = intel_rng_init,
  184. .cleanup = intel_rng_cleanup,
  185. .data_present = intel_rng_data_present,
  186. .data_read = intel_rng_data_read,
  187. };
  188. #ifdef CONFIG_SMP
  189. static char __initdata waitflag;
  190. static void __init intel_init_wait(void *unused)
  191. {
  192. while (waitflag)
  193. cpu_relax();
  194. }
  195. #endif
  196. static int __init mod_init(void)
  197. {
  198. int err = -ENODEV;
  199. unsigned i;
  200. struct pci_dev *dev = NULL;
  201. void __iomem *mem;
  202. unsigned long flags;
  203. u8 bios_cntl_off, fwh_dec_en1_off;
  204. u8 bios_cntl_val = 0xff, fwh_dec_en1_val = 0xff;
  205. u8 hw_status, mfc, dvc;
  206. for (i = 0; !dev && pci_tbl[i].vendor; ++i)
  207. dev = pci_get_device(pci_tbl[i].vendor, pci_tbl[i].device, NULL);
  208. if (!dev)
  209. goto out; /* Device not found. */
  210. /* Check for Intel 82802 */
  211. if (dev->device < 0x2640) {
  212. fwh_dec_en1_off = FWH_DEC_EN1_REG_OLD;
  213. bios_cntl_off = BIOS_CNTL_REG_OLD;
  214. } else {
  215. fwh_dec_en1_off = FWH_DEC_EN1_REG_NEW;
  216. bios_cntl_off = BIOS_CNTL_REG_NEW;
  217. }
  218. pci_read_config_byte(dev, fwh_dec_en1_off, &fwh_dec_en1_val);
  219. pci_read_config_byte(dev, bios_cntl_off, &bios_cntl_val);
  220. mem = ioremap_nocache(INTEL_FWH_ADDR, INTEL_FWH_ADDR_LEN);
  221. if (mem == NULL) {
  222. pci_dev_put(dev);
  223. err = -EBUSY;
  224. goto out;
  225. }
  226. /*
  227. * Since the BIOS code/data is going to disappear from its normal
  228. * location with the Read ID command, all activity on the system
  229. * must be stopped until the state is back to normal.
  230. */
  231. #ifdef CONFIG_SMP
  232. set_mb(waitflag, 1);
  233. if (smp_call_function(intel_init_wait, NULL, 1, 0) != 0) {
  234. set_mb(waitflag, 0);
  235. pci_dev_put(dev);
  236. printk(KERN_ERR PFX "cannot run on all processors\n");
  237. err = -EAGAIN;
  238. goto err_unmap;
  239. }
  240. #endif
  241. local_irq_save(flags);
  242. if (!(fwh_dec_en1_val & FWH_F8_EN_MASK))
  243. pci_write_config_byte(dev,
  244. fwh_dec_en1_off,
  245. fwh_dec_en1_val | FWH_F8_EN_MASK);
  246. if (!(bios_cntl_val &
  247. (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK)))
  248. pci_write_config_byte(dev,
  249. bios_cntl_off,
  250. bios_cntl_val | BIOS_CNTL_WRITE_ENABLE_MASK);
  251. writeb(INTEL_FWH_RESET_CMD, mem);
  252. writeb(INTEL_FWH_READ_ID_CMD, mem);
  253. mfc = readb(mem + INTEL_FWH_MANUFACTURER_CODE_ADDRESS);
  254. dvc = readb(mem + INTEL_FWH_DEVICE_CODE_ADDRESS);
  255. writeb(INTEL_FWH_RESET_CMD, mem);
  256. if (!(bios_cntl_val &
  257. (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK)))
  258. pci_write_config_byte(dev, bios_cntl_off, bios_cntl_val);
  259. if (!(fwh_dec_en1_val & FWH_F8_EN_MASK))
  260. pci_write_config_byte(dev, fwh_dec_en1_off, fwh_dec_en1_val);
  261. local_irq_restore(flags);
  262. #ifdef CONFIG_SMP
  263. /* Tell other CPUs to resume. */
  264. set_mb(waitflag, 0);
  265. #endif
  266. iounmap(mem);
  267. pci_dev_put(dev);
  268. if (mfc != INTEL_FWH_MANUFACTURER_CODE ||
  269. (dvc != INTEL_FWH_DEVICE_CODE_8M &&
  270. dvc != INTEL_FWH_DEVICE_CODE_4M)) {
  271. printk(KERN_ERR PFX "FWH not detected\n");
  272. err = -ENODEV;
  273. goto out;
  274. }
  275. err = -ENOMEM;
  276. mem = ioremap(INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN);
  277. if (!mem)
  278. goto out;
  279. intel_rng.priv = (unsigned long)mem;
  280. /* Check for Random Number Generator */
  281. err = -ENODEV;
  282. hw_status = hwstatus_get(mem);
  283. if ((hw_status & INTEL_RNG_PRESENT) == 0)
  284. goto err_unmap;
  285. printk(KERN_INFO "Intel 82802 RNG detected\n");
  286. err = hwrng_register(&intel_rng);
  287. if (err) {
  288. printk(KERN_ERR PFX "RNG registering failed (%d)\n",
  289. err);
  290. goto err_unmap;
  291. }
  292. out:
  293. return err;
  294. err_unmap:
  295. iounmap(mem);
  296. goto out;
  297. }
  298. static void __exit mod_exit(void)
  299. {
  300. void __iomem *mem = (void __iomem *)intel_rng.priv;
  301. hwrng_unregister(&intel_rng);
  302. iounmap(mem);
  303. }
  304. subsys_initcall(mod_init);
  305. module_exit(mod_exit);
  306. MODULE_DESCRIPTION("H/W RNG driver for Intel chipsets");
  307. MODULE_LICENSE("GPL");