X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fchar%2Fhw_random.c;h=29dc87e59020466ab8e7595f3ebf28e2e7e66d8b;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=090ce07a18a828edaf0f7655c94a46d139190e9a;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/drivers/char/hw_random.c b/drivers/char/hw_random.c index 090ce07a1..29dc87e59 100644 --- a/drivers/char/hw_random.c +++ b/drivers/char/hw_random.c @@ -1,4 +1,9 @@ /* + Added support for the AMD Geode LX RNG + (c) Copyright 2004-2005 Advanced Micro Devices, Inc. + + derived from + Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG) (c) Copyright 2003 Red Hat Inc @@ -56,31 +61,27 @@ /* * debugging macros */ -#undef RNG_DEBUG /* define to enable copious debugging info */ -#ifdef RNG_DEBUG -/* note: prints function name for you */ -#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) -#else -#define DPRINTK(fmt, args...) -#endif +/* pr_debug() collapses to a no-op if DEBUG is not defined */ +#define DPRINTK(fmt, args...) pr_debug(PFX "%s: " fmt, __FUNCTION__ , ## args) + -#define RNG_NDEBUG /* define to disable lightweight runtime checks */ +#undef RNG_NDEBUG /* define to enable lightweight runtime checks */ #ifdef RNG_NDEBUG -#define assert(expr) +#define assert(expr) \ + if(!(expr)) { \ + printk(KERN_DEBUG PFX "Assertion failed! %s,%s,%s," \ + "line=%d\n", #expr, __FILE__, __FUNCTION__, __LINE__); \ + } #else -#define assert(expr) \ - if(!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } +#define assert(expr) #endif #define RNG_MISCDEV_MINOR 183 /* official */ static int rng_dev_open (struct inode *inode, struct file *filp); static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size, - loff_t * offp); + loff_t * offp); static int __init intel_init (struct pci_dev *dev); static void intel_cleanup(void); @@ -99,6 +100,11 @@ static unsigned int via_data_present (void); static u32 via_data_read (void); #endif +static int __init geode_init(struct pci_dev *dev); +static void geode_cleanup(void); +static unsigned int geode_data_present (void); +static u32 geode_data_read (void); + struct rng_operations { int (*init) (struct pci_dev *dev); void (*cleanup) (void); @@ -125,7 +131,10 @@ enum { rng_hw_none, rng_hw_intel, rng_hw_amd, +#ifdef __i386__ rng_hw_via, +#endif + rng_hw_geode, }; static struct rng_operations rng_vendor_ops[] = { @@ -143,6 +152,9 @@ static struct rng_operations rng_vendor_ops[] = { /* rng_hw_via */ { via_init, via_cleanup, via_data_present, via_data_read, 1 }, #endif + + /* rng_hw_geode */ + { geode_init, geode_cleanup, geode_data_present, geode_data_read, 4 } }; /* @@ -159,10 +171,14 @@ static struct pci_device_id rng_pci_tbl[] = { { 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, { 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, + { 0x8086, 0x2430, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, { 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, { 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, { 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LX_AES, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_geode }, + { 0, }, /* terminate list */ }; MODULE_DEVICE_TABLE (pci, rng_pci_tbl); @@ -191,7 +207,7 @@ MODULE_DEVICE_TABLE (pci, rng_pci_tbl); #define INTEL_RNG_ADDR_LEN 3 /* token to our ioremap'd RNG register area */ -static void *rng_mem; +static void __iomem *rng_mem; static inline u8 intel_hwstatus (void) { @@ -322,7 +338,8 @@ static int __init amd_init (struct pci_dev *dev) rnen |= (1 << 7); /* PMIO enable */ pci_write_config_byte(dev, 0x41, rnen); - printk(KERN_INFO PFX "AMD768 system management I/O registers at 0x%X.\n", pmbase); + pr_info( PFX "AMD768 system management I/O registers at 0x%X.\n", + pmbase); amd_dev = dev; @@ -369,7 +386,7 @@ enum { VIA_RNG_CHUNK_1_MASK = 0xFF, }; -u32 via_rng_datum; +static u32 via_rng_datum; /* * Investigate using the 'rep' prefix to obtain 32 bits of random data @@ -463,6 +480,57 @@ static void via_cleanup(void) } #endif +/*********************************************************************** + * + * AMD Geode RNG operations + * + */ + +static void __iomem *geode_rng_base = NULL; + +#define GEODE_RNG_DATA_REG 0x50 +#define GEODE_RNG_STATUS_REG 0x54 + +static u32 geode_data_read(void) +{ + u32 val; + + assert(geode_rng_base != NULL); + val = readl(geode_rng_base + GEODE_RNG_DATA_REG); + return val; +} + +static unsigned int geode_data_present(void) +{ + u32 val; + + assert(geode_rng_base != NULL); + val = readl(geode_rng_base + GEODE_RNG_STATUS_REG); + return val; +} + +static void geode_cleanup(void) +{ + iounmap(geode_rng_base); + geode_rng_base = NULL; +} + +static int geode_init(struct pci_dev *dev) +{ + unsigned long rng_base = pci_resource_start(dev, 0); + + if (rng_base == 0) + return 1; + + geode_rng_base = ioremap(rng_base, 0x58); + + if (geode_rng_base == NULL) { + printk(KERN_ERR PFX "Cannot ioremap RNG memory\n"); + return -EBUSY; + } + + return 0; +} /*********************************************************************** * @@ -483,9 +551,9 @@ static int rng_dev_open (struct inode *inode, struct file *filp) static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size, - loff_t * offp) + loff_t * offp) { - static spinlock_t rng_lock = SPIN_LOCK_UNLOCKED; + static DEFINE_SPINLOCK(rng_lock); unsigned int have_data; u32 data = 0; ssize_t ret = 0; @@ -516,10 +584,7 @@ static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size, return ret ? : -EAGAIN; if(need_resched()) - { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); - } + schedule_timeout_interruptible(1); else udelay(200); /* FIXME: We could poll for 250uS ?? */ @@ -580,9 +645,9 @@ static int __init rng_init (void) DPRINTK ("ENTER\n"); - /* Probe for Intel, AMD RNGs */ - while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) { - ent = pci_match_device (rng_pci_tbl, pdev); + /* Probe for Intel, AMD, Geode RNGs */ + for_each_pci_dev(pdev) { + ent = pci_match_id(rng_pci_tbl, pdev); if (ent) { rng_ops = &rng_vendor_ops[ent->driver_data]; goto match; @@ -606,7 +671,7 @@ match: if (rc) return rc; - printk (KERN_INFO RNG_DRIVER_NAME " loaded\n"); + pr_info( RNG_DRIVER_NAME " loaded\n"); DPRINTK ("EXIT, returning 0\n"); return 0;