diff -urN linux-2.4.36-alb25.6/drivers/char/Config.in linux-2.4.36-alb25.6-geode/drivers/char/Config.in --- linux-2.4.36-alb25.6/drivers/char/Config.in 2007-08-07 12:51:46 +0200 +++ linux-2.4.36-alb25.6-geode/drivers/char/Config.in 2008-09-01 12:57:43 +0200 @@ -345,6 +345,9 @@ "$CONFIG_X86_64" = "y" ]; then dep_tristate 'Intel/AMD/VIA HW Random Number Generator support' CONFIG_HW_RANDOM $CONFIG_PCI fi +if [ "$CONFIG_X86" = "y" ]; then + dep_tristate 'AMD Geode Random Number Generator support' CONFIG_GEODE_RNG $CONFIG_PCI +fi dep_tristate 'AMD 76x native power management (Experimental)' CONFIG_AMD_PM768 $CONFIG_PCI tristate '/dev/nvram support' CONFIG_NVRAM tristate 'Enhanced Real Time Clock Support' CONFIG_RTC diff -urN linux-2.4.36-alb25.6/drivers/char/Makefile linux-2.4.36-alb25.6-geode/drivers/char/Makefile --- linux-2.4.36-alb25.6/drivers/char/Makefile 2007-08-07 12:51:46 +0200 +++ linux-2.4.36-alb25.6-geode/drivers/char/Makefile 2008-09-01 12:57:43 +0200 @@ -264,6 +264,7 @@ obj-$(CONFIG_DS1742) += ds1742.o obj-$(CONFIG_INTEL_RNG) += i810_rng.o obj-$(CONFIG_AMD_RNG) += amd768_rng.o +obj-$(CONFIG_GEODE_RNG) += geode-rng.o obj-$(CONFIG_HW_RANDOM) += hw_random.o obj-$(CONFIG_AMD_PM768) += amd76x_pm.o obj-$(CONFIG_BRIQ_PANEL) += briq_panel.o diff -urN linux-2.4.36-alb25.6/drivers/char/geode-rng.c linux-2.4.36-alb25.6-geode/drivers/char/geode-rng.c --- linux-2.4.36-alb25.6/drivers/char/geode-rng.c 1970-01-01 01:00:00 +0100 +++ linux-2.4.36-alb25.6-geode/drivers/char/geode-rng.c 2008-09-01 13:07:07 +0200 @@ -0,0 +1,114 @@ +/* + * RNG driver for AMD Geode RNGs + * + * Copyright 2008 Willy Tarreau + * + * Inspired by drivers/char/hw_random/geode-rng.c from kernel 2.6.25. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* We read the random generator every 50 ms */ +#define RNG_INTERVAL (HZ/20+1) + +#define GEODE_RNG_DATA_REG 0x50 +#define GEODE_RNG_STATUS_REG 0x54 + +static struct timer_list timer; +static void __iomem *rng_addr; +static u32 rng_data[2]; +static int nb_data; + +static u32 geode_rng_data_read(void) +{ + return readl(rng_addr + GEODE_RNG_DATA_REG); +} + +static int geode_rng_data_present(void) +{ + return !!(readl(rng_addr + GEODE_RNG_STATUS_REG)); +} + +static void geode_rng_timer(unsigned long data) +{ + if (!geode_rng_data_present()) + goto out; + + rng_data[nb_data] = geode_rng_data_read(); + nb_data++; + if (nb_data > 1) { + nb_data = 0; + /* We have collected 64 bits. Maybe we should reduce the + * announced entropy ? At least, check for changing data + * and refuse to feed consts. + */ + if (rng_data[0] != rng_data[1]) + batch_entropy_store(rng_data[0], rng_data[1], 64); + } + out: + timer.expires = jiffies + RNG_INTERVAL; + add_timer(&timer); +} + +static int __init geode_rng_init(void) +{ + struct pci_dev *pdev = NULL; + unsigned long rng_base; + int err = -ENODEV; + + pdev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LX_AES, NULL); + + if (pdev == NULL) { + printk(KERN_ERR "geode-rng: AMD Geode RNG device not found\n"); + goto out; + } + + if ((err = pci_enable_device(pdev))) + goto out; + + if ((err = pci_enable_device_bars(pdev, 1))) + goto out; + + rng_base = pci_resource_start(pdev, 0); + if (rng_base == 0) + goto out; + + err = -ENOMEM; + rng_addr = ioremap(rng_base, 0x58); + if (!rng_addr) + goto out; + + printk(KERN_INFO "AMD Geode RNG detected and enabled\n"); + + init_timer(&timer); + timer.function = geode_rng_timer; + timer.data = 0; + timer.expires = jiffies + RNG_INTERVAL; + add_timer(&timer); + err = 0; +out: + return err; +} + +static void __exit geode_rng_exit(void) +{ + del_timer_sync(&timer); + iounmap(rng_addr); +} + +module_init(geode_rng_init); +module_exit(geode_rng_exit); + +MODULE_AUTHOR("Willy Tarreau"); +MODULE_LICENSE("GPL"); diff -urN linux-2.4.36-alb25.6/include/linux/pci_ids.h linux-2.4.36-alb25.6-geode/include/linux/pci_ids.h --- linux-2.4.36-alb25.6/include/linux/pci_ids.h 2008-01-21 11:00:40 +0100 +++ linux-2.4.36-alb25.6-geode/include/linux/pci_ids.h 2008-09-01 13:03:20 +0200 @@ -434,6 +434,7 @@ #define PCI_DEVICE_ID_AMD_LANCE 0x2000 #define PCI_DEVICE_ID_AMD_LANCE_HOME 0x2001 #define PCI_DEVICE_ID_AMD_SCSI 0x2020 +#define PCI_DEVICE_ID_AMD_LX_AES 0x2082 #define PCI_DEVICE_ID_AMD_CS5536_ISA 0x2090 #define PCI_DEVICE_ID_AMD_CS5536_IDE 0x209A #define PCI_DEVICE_ID_AMD_SERENADE 0x36c0 #define PCI_DEVICE_ID_AMD_FE_GATE_7006 0x7006