mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
94 lines
2.1 KiB
94 lines
2.1 KiB
/* |
|
* Hardware Random Number Generator support for Cavium, Inc. |
|
* Thunder processor family. |
|
* |
|
* This file is subject to the terms and conditions of the GNU General Public |
|
* License. See the file "COPYING" in the main directory of this archive |
|
* for more details. |
|
* |
|
* Copyright (C) 2016 Cavium, Inc. |
|
*/ |
|
|
|
#include <linux/hw_random.h> |
|
#include <linux/io.h> |
|
#include <linux/module.h> |
|
#include <linux/pci.h> |
|
#include <linux/pci_ids.h> |
|
|
|
struct cavium_rng { |
|
struct hwrng ops; |
|
void __iomem *result; |
|
}; |
|
|
|
/* Read data from the RNG unit */ |
|
static int cavium_rng_read(struct hwrng *rng, void *dat, size_t max, bool wait) |
|
{ |
|
struct cavium_rng *p = container_of(rng, struct cavium_rng, ops); |
|
unsigned int size = max; |
|
|
|
while (size >= 8) { |
|
*((u64 *)dat) = readq(p->result); |
|
size -= 8; |
|
dat += 8; |
|
} |
|
while (size > 0) { |
|
*((u8 *)dat) = readb(p->result); |
|
size--; |
|
dat++; |
|
} |
|
return max; |
|
} |
|
|
|
/* Map Cavium RNG to an HWRNG object */ |
|
static int cavium_rng_probe_vf(struct pci_dev *pdev, |
|
const struct pci_device_id *id) |
|
{ |
|
struct cavium_rng *rng; |
|
int ret; |
|
|
|
rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL); |
|
if (!rng) |
|
return -ENOMEM; |
|
|
|
/* Map the RNG result */ |
|
rng->result = pcim_iomap(pdev, 0, 0); |
|
if (!rng->result) { |
|
dev_err(&pdev->dev, "Error iomap failed retrieving result.\n"); |
|
return -ENOMEM; |
|
} |
|
|
|
rng->ops.name = devm_kasprintf(&pdev->dev, GFP_KERNEL, |
|
"cavium-rng-%s", dev_name(&pdev->dev)); |
|
if (!rng->ops.name) |
|
return -ENOMEM; |
|
|
|
rng->ops.read = cavium_rng_read; |
|
rng->ops.quality = 1000; |
|
|
|
pci_set_drvdata(pdev, rng); |
|
|
|
ret = devm_hwrng_register(&pdev->dev, &rng->ops); |
|
if (ret) { |
|
dev_err(&pdev->dev, "Error registering device as HWRNG.\n"); |
|
return ret; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
|
|
static const struct pci_device_id cavium_rng_vf_id_table[] = { |
|
{ PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 0xa033), 0, 0, 0}, |
|
{0,}, |
|
}; |
|
MODULE_DEVICE_TABLE(pci, cavium_rng_vf_id_table); |
|
|
|
static struct pci_driver cavium_rng_vf_driver = { |
|
.name = "cavium_rng_vf", |
|
.id_table = cavium_rng_vf_id_table, |
|
.probe = cavium_rng_probe_vf, |
|
}; |
|
module_pci_driver(cavium_rng_vf_driver); |
|
|
|
MODULE_AUTHOR("Omer Khaliq <[email protected]>"); |
|
MODULE_LICENSE("GPL");
|
|
|