1 /* 2 * RNG driver for AMD 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 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 27 #include <linux/delay.h> 28 #include <linux/hw_random.h> 29 #include <linux/io.h> 30 #include <linux/kernel.h> 31 #include <linux/module.h> 32 #include <linux/pci.h> 33 34 #define DRV_NAME "AMD768-HWRNG" 35 36 #define RNGDATA 0x00 37 #define RNGDONE 0x04 38 #define PMBASE_OFFSET 0xF0 39 #define PMBASE_SIZE 8 40 41 /* 42 * Data for PCI driver interface 43 * 44 * This data only exists for exporting the supported 45 * PCI ids via MODULE_DEVICE_TABLE. We do not actually 46 * register a pci_driver, because someone else might one day 47 * want to register another driver on the same PCI id. 48 */ 49 static const struct pci_device_id pci_tbl[] = { 50 { PCI_VDEVICE(AMD, 0x7443), 0, }, 51 { PCI_VDEVICE(AMD, 0x746b), 0, }, 52 { 0, }, /* terminate list */ 53 }; 54 MODULE_DEVICE_TABLE(pci, pci_tbl); 55 56 struct amd768_priv { 57 void __iomem *iobase; 58 struct pci_dev *pcidev; 59 u32 pmbase; 60 }; 61 62 static int amd_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait) 63 { 64 u32 *data = buf; 65 struct amd768_priv *priv = (struct amd768_priv *)rng->priv; 66 size_t read = 0; 67 /* We will wait at maximum one time per read */ 68 int timeout = max / 4 + 1; 69 70 /* 71 * RNG data is available when RNGDONE is set to 1 72 * New random numbers are generated approximately 128 microseconds 73 * after RNGDATA is read 74 */ 75 while (read < max) { 76 if (ioread32(priv->iobase + RNGDONE) == 0) { 77 if (wait) { 78 /* Delay given by datasheet */ 79 usleep_range(128, 196); 80 if (timeout-- == 0) 81 return read; 82 } else { 83 return 0; 84 } 85 } else { 86 *data = ioread32(priv->iobase + RNGDATA); 87 data++; 88 read += 4; 89 } 90 } 91 92 return read; 93 } 94 95 static int amd_rng_init(struct hwrng *rng) 96 { 97 struct amd768_priv *priv = (struct amd768_priv *)rng->priv; 98 u8 rnen; 99 100 pci_read_config_byte(priv->pcidev, 0x40, &rnen); 101 rnen |= BIT(7); /* RNG on */ 102 pci_write_config_byte(priv->pcidev, 0x40, rnen); 103 104 pci_read_config_byte(priv->pcidev, 0x41, &rnen); 105 rnen |= BIT(7); /* PMIO enable */ 106 pci_write_config_byte(priv->pcidev, 0x41, rnen); 107 108 return 0; 109 } 110 111 static void amd_rng_cleanup(struct hwrng *rng) 112 { 113 struct amd768_priv *priv = (struct amd768_priv *)rng->priv; 114 u8 rnen; 115 116 pci_read_config_byte(priv->pcidev, 0x40, &rnen); 117 rnen &= ~BIT(7); /* RNG off */ 118 pci_write_config_byte(priv->pcidev, 0x40, rnen); 119 } 120 121 static struct hwrng amd_rng = { 122 .name = "amd", 123 .init = amd_rng_init, 124 .cleanup = amd_rng_cleanup, 125 .read = amd_rng_read, 126 }; 127 128 static int __init amd_rng_mod_init(void) 129 { 130 int err; 131 struct pci_dev *pdev = NULL; 132 const struct pci_device_id *ent; 133 u32 pmbase; 134 struct amd768_priv *priv; 135 136 for_each_pci_dev(pdev) { 137 ent = pci_match_id(pci_tbl, pdev); 138 if (ent) 139 goto found; 140 } 141 /* Device not found. */ 142 return -ENODEV; 143 144 found: 145 err = pci_read_config_dword(pdev, 0x58, &pmbase); 146 if (err) { 147 err = pcibios_err_to_errno(err); 148 goto put_dev; 149 } 150 151 pmbase &= 0x0000FF00; 152 if (pmbase == 0) { 153 err = -EIO; 154 goto put_dev; 155 } 156 157 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 158 if (!priv) { 159 err = -ENOMEM; 160 goto put_dev; 161 } 162 163 if (!request_region(pmbase + PMBASE_OFFSET, PMBASE_SIZE, DRV_NAME)) { 164 dev_err(&pdev->dev, DRV_NAME " region 0x%x already in use!\n", 165 pmbase + 0xF0); 166 err = -EBUSY; 167 goto out; 168 } 169 170 priv->iobase = ioport_map(pmbase + PMBASE_OFFSET, PMBASE_SIZE); 171 if (!priv->iobase) { 172 pr_err(DRV_NAME "Cannot map ioport\n"); 173 err = -EINVAL; 174 goto err_iomap; 175 } 176 177 amd_rng.priv = (unsigned long)priv; 178 priv->pmbase = pmbase; 179 priv->pcidev = pdev; 180 181 pr_info(DRV_NAME " detected\n"); 182 err = hwrng_register(&amd_rng); 183 if (err) { 184 pr_err(DRV_NAME " registering failed (%d)\n", err); 185 goto err_hwrng; 186 } 187 return 0; 188 189 err_hwrng: 190 ioport_unmap(priv->iobase); 191 err_iomap: 192 release_region(pmbase + PMBASE_OFFSET, PMBASE_SIZE); 193 out: 194 kfree(priv); 195 put_dev: 196 pci_dev_put(pdev); 197 return err; 198 } 199 200 static void __exit amd_rng_mod_exit(void) 201 { 202 struct amd768_priv *priv; 203 204 priv = (struct amd768_priv *)amd_rng.priv; 205 206 hwrng_unregister(&amd_rng); 207 208 ioport_unmap(priv->iobase); 209 210 release_region(priv->pmbase + PMBASE_OFFSET, PMBASE_SIZE); 211 212 pci_dev_put(priv->pcidev); 213 214 kfree(priv); 215 } 216 217 module_init(amd_rng_mod_init); 218 module_exit(amd_rng_mod_exit); 219 220 MODULE_AUTHOR("The Linux Kernel team"); 221 MODULE_DESCRIPTION("H/W RNG driver for AMD chipsets"); 222 MODULE_LICENSE("GPL"); 223