aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/hw_random.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/hw_random.c')
-rw-r--r--drivers/char/hw_random.c70
1 files changed, 69 insertions, 1 deletions
diff --git a/drivers/char/hw_random.c b/drivers/char/hw_random.c
index 6f673d2de0b1..49769f59ea1b 100644
--- a/drivers/char/hw_random.c
+++ b/drivers/char/hw_random.c
@@ -1,4 +1,9 @@
1/* 1/*
2 Added support for the AMD Geode LX RNG
3 (c) Copyright 2004-2005 Advanced Micro Devices, Inc.
4
5 derived from
6
2 Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG) 7 Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
3 (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com> 8 (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
4 9
@@ -95,6 +100,11 @@ static unsigned int via_data_present (void);
95static u32 via_data_read (void); 100static u32 via_data_read (void);
96#endif 101#endif
97 102
103static int __init geode_init(struct pci_dev *dev);
104static void geode_cleanup(void);
105static unsigned int geode_data_present (void);
106static u32 geode_data_read (void);
107
98struct rng_operations { 108struct rng_operations {
99 int (*init) (struct pci_dev *dev); 109 int (*init) (struct pci_dev *dev);
100 void (*cleanup) (void); 110 void (*cleanup) (void);
@@ -122,6 +132,7 @@ enum {
122 rng_hw_intel, 132 rng_hw_intel,
123 rng_hw_amd, 133 rng_hw_amd,
124 rng_hw_via, 134 rng_hw_via,
135 rng_hw_geode,
125}; 136};
126 137
127static struct rng_operations rng_vendor_ops[] = { 138static struct rng_operations rng_vendor_ops[] = {
@@ -139,6 +150,9 @@ static struct rng_operations rng_vendor_ops[] = {
139 /* rng_hw_via */ 150 /* rng_hw_via */
140 { via_init, via_cleanup, via_data_present, via_data_read, 1 }, 151 { via_init, via_cleanup, via_data_present, via_data_read, 1 },
141#endif 152#endif
153
154 /* rng_hw_geode */
155 { geode_init, geode_cleanup, geode_data_present, geode_data_read, 4 }
142}; 156};
143 157
144/* 158/*
@@ -159,6 +173,9 @@ static struct pci_device_id rng_pci_tbl[] = {
159 { 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, 173 { 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
160 { 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, 174 { 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
161 175
176 { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LX_AES,
177 PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_geode },
178
162 { 0, }, /* terminate list */ 179 { 0, }, /* terminate list */
163}; 180};
164MODULE_DEVICE_TABLE (pci, rng_pci_tbl); 181MODULE_DEVICE_TABLE (pci, rng_pci_tbl);
@@ -460,6 +477,57 @@ static void via_cleanup(void)
460} 477}
461#endif 478#endif
462 479
480/***********************************************************************
481 *
482 * AMD Geode RNG operations
483 *
484 */
485
486static void __iomem *geode_rng_base = NULL;
487
488#define GEODE_RNG_DATA_REG 0x50
489#define GEODE_RNG_STATUS_REG 0x54
490
491static u32 geode_data_read(void)
492{
493 u32 val;
494
495 assert(geode_rng_base != NULL);
496 val = readl(geode_rng_base + GEODE_RNG_DATA_REG);
497 return val;
498}
499
500static unsigned int geode_data_present(void)
501{
502 u32 val;
503
504 assert(geode_rng_base != NULL);
505 val = readl(geode_rng_base + GEODE_RNG_STATUS_REG);
506 return val;
507}
508
509static void geode_cleanup(void)
510{
511 iounmap(geode_rng_base);
512 geode_rng_base = NULL;
513}
514
515static int geode_init(struct pci_dev *dev)
516{
517 unsigned long rng_base = pci_resource_start(dev, 0);
518
519 if (rng_base == 0)
520 return 1;
521
522 geode_rng_base = ioremap(rng_base, 0x58);
523
524 if (geode_rng_base == NULL) {
525 printk(KERN_ERR PFX "Cannot ioremap RNG memory\n");
526 return -EBUSY;
527 }
528
529 return 0;
530}
463 531
464/*********************************************************************** 532/***********************************************************************
465 * 533 *
@@ -574,7 +642,7 @@ static int __init rng_init (void)
574 642
575 DPRINTK ("ENTER\n"); 643 DPRINTK ("ENTER\n");
576 644
577 /* Probe for Intel, AMD RNGs */ 645 /* Probe for Intel, AMD, Geode RNGs */
578 for_each_pci_dev(pdev) { 646 for_each_pci_dev(pdev) {
579 ent = pci_match_id(rng_pci_tbl, pdev); 647 ent = pci_match_id(rng_pci_tbl, pdev);
580 if (ent) { 648 if (ent) {