Linux Audio

Check our new training course

Loading...
v6.8
  1/*
  2 * RNG driver for AMD Geode 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
 35#define PFX	KBUILD_MODNAME ": "
 36
 37#define GEODE_RNG_DATA_REG   0x50
 38#define GEODE_RNG_STATUS_REG 0x54
 39
 40/*
 41 * Data for PCI driver interface
 42 *
 43 * This data only exists for exporting the supported
 44 * PCI ids via MODULE_DEVICE_TABLE.  We do not actually
 45 * register a pci_driver, because someone else might one day
 46 * want to register another driver on the same PCI id.
 47 */
 48static const struct pci_device_id pci_tbl[] = {
 49	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_LX_AES), 0, },
 50	{ 0, },	/* terminate list */
 51};
 52MODULE_DEVICE_TABLE(pci, pci_tbl);
 53
 54struct amd_geode_priv {
 55	struct pci_dev *pcidev;
 56	void __iomem *membase;
 57};
 58
 59static int geode_rng_data_read(struct hwrng *rng, u32 *data)
 60{
 61	struct amd_geode_priv *priv = (struct amd_geode_priv *)rng->priv;
 62	void __iomem *mem = priv->membase;
 63
 64	*data = readl(mem + GEODE_RNG_DATA_REG);
 65
 66	return 4;
 67}
 68
 69static int geode_rng_data_present(struct hwrng *rng, int wait)
 70{
 71	struct amd_geode_priv *priv = (struct amd_geode_priv *)rng->priv;
 72	void __iomem *mem = priv->membase;
 73	int data, i;
 74
 75	for (i = 0; i < 20; i++) {
 76		data = !!(readl(mem + GEODE_RNG_STATUS_REG));
 77		if (data || !wait)
 78			break;
 79		udelay(10);
 80	}
 81	return data;
 82}
 83
 84
 85static struct hwrng geode_rng = {
 86	.name		= "geode",
 87	.data_present	= geode_rng_data_present,
 88	.data_read	= geode_rng_data_read,
 89};
 90
 91
 92static int __init geode_rng_init(void)
 93{
 94	int err = -ENODEV;
 95	struct pci_dev *pdev = NULL;
 96	const struct pci_device_id *ent;
 97	void __iomem *mem;
 98	unsigned long rng_base;
 99	struct amd_geode_priv *priv;
100
101	for_each_pci_dev(pdev) {
102		ent = pci_match_id(pci_tbl, pdev);
103		if (ent)
104			goto found;
105	}
106	/* Device not found. */
107	return err;
108
109found:
110	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
111	if (!priv) {
112		err = -ENOMEM;
113		goto put_dev;
114	}
115
116	rng_base = pci_resource_start(pdev, 0);
117	if (rng_base == 0)
118		goto free_priv;
119	err = -ENOMEM;
120	mem = ioremap(rng_base, 0x58);
121	if (!mem)
122		goto free_priv;
123
124	geode_rng.priv = (unsigned long)priv;
125	priv->membase = mem;
126	priv->pcidev = pdev;
127
128	pr_info("AMD Geode RNG detected\n");
129	err = hwrng_register(&geode_rng);
130	if (err) {
131		pr_err(PFX "RNG registering failed (%d)\n",
132		       err);
133		goto err_unmap;
134	}
135	return err;
136
137err_unmap:
138	iounmap(mem);
139free_priv:
140	kfree(priv);
141put_dev:
142	pci_dev_put(pdev);
143	return err;
144}
145
146static void __exit geode_rng_exit(void)
147{
148	struct amd_geode_priv *priv;
149
150	priv = (struct amd_geode_priv *)geode_rng.priv;
151	hwrng_unregister(&geode_rng);
152	iounmap(priv->membase);
153	pci_dev_put(priv->pcidev);
154	kfree(priv);
155}
156
157module_init(geode_rng_init);
158module_exit(geode_rng_exit);
159
160MODULE_DESCRIPTION("H/W RNG driver for AMD Geode LX CPUs");
161MODULE_LICENSE("GPL");
v6.2
  1/*
  2 * RNG driver for AMD Geode 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
 35#define PFX	KBUILD_MODNAME ": "
 36
 37#define GEODE_RNG_DATA_REG   0x50
 38#define GEODE_RNG_STATUS_REG 0x54
 39
 40/*
 41 * Data for PCI driver interface
 42 *
 43 * This data only exists for exporting the supported
 44 * PCI ids via MODULE_DEVICE_TABLE.  We do not actually
 45 * register a pci_driver, because someone else might one day
 46 * want to register another driver on the same PCI id.
 47 */
 48static const struct pci_device_id pci_tbl[] = {
 49	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_LX_AES), 0, },
 50	{ 0, },	/* terminate list */
 51};
 52MODULE_DEVICE_TABLE(pci, pci_tbl);
 53
 54struct amd_geode_priv {
 55	struct pci_dev *pcidev;
 56	void __iomem *membase;
 57};
 58
 59static int geode_rng_data_read(struct hwrng *rng, u32 *data)
 60{
 61	void __iomem *mem = (void __iomem *)rng->priv;
 
 62
 63	*data = readl(mem + GEODE_RNG_DATA_REG);
 64
 65	return 4;
 66}
 67
 68static int geode_rng_data_present(struct hwrng *rng, int wait)
 69{
 70	void __iomem *mem = (void __iomem *)rng->priv;
 
 71	int data, i;
 72
 73	for (i = 0; i < 20; i++) {
 74		data = !!(readl(mem + GEODE_RNG_STATUS_REG));
 75		if (data || !wait)
 76			break;
 77		udelay(10);
 78	}
 79	return data;
 80}
 81
 82
 83static struct hwrng geode_rng = {
 84	.name		= "geode",
 85	.data_present	= geode_rng_data_present,
 86	.data_read	= geode_rng_data_read,
 87};
 88
 89
 90static int __init geode_rng_init(void)
 91{
 92	int err = -ENODEV;
 93	struct pci_dev *pdev = NULL;
 94	const struct pci_device_id *ent;
 95	void __iomem *mem;
 96	unsigned long rng_base;
 97	struct amd_geode_priv *priv;
 98
 99	for_each_pci_dev(pdev) {
100		ent = pci_match_id(pci_tbl, pdev);
101		if (ent)
102			goto found;
103	}
104	/* Device not found. */
105	return err;
106
107found:
108	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
109	if (!priv) {
110		err = -ENOMEM;
111		goto put_dev;
112	}
113
114	rng_base = pci_resource_start(pdev, 0);
115	if (rng_base == 0)
116		goto free_priv;
117	err = -ENOMEM;
118	mem = ioremap(rng_base, 0x58);
119	if (!mem)
120		goto free_priv;
121
122	geode_rng.priv = (unsigned long)priv;
123	priv->membase = mem;
124	priv->pcidev = pdev;
125
126	pr_info("AMD Geode RNG detected\n");
127	err = hwrng_register(&geode_rng);
128	if (err) {
129		pr_err(PFX "RNG registering failed (%d)\n",
130		       err);
131		goto err_unmap;
132	}
133	return err;
134
135err_unmap:
136	iounmap(mem);
137free_priv:
138	kfree(priv);
139put_dev:
140	pci_dev_put(pdev);
141	return err;
142}
143
144static void __exit geode_rng_exit(void)
145{
146	struct amd_geode_priv *priv;
147
148	priv = (struct amd_geode_priv *)geode_rng.priv;
149	hwrng_unregister(&geode_rng);
150	iounmap(priv->membase);
151	pci_dev_put(priv->pcidev);
152	kfree(priv);
153}
154
155module_init(geode_rng_init);
156module_exit(geode_rng_exit);
157
158MODULE_DESCRIPTION("H/W RNG driver for AMD Geode LX CPUs");
159MODULE_LICENSE("GPL");