123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- /*
- * 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 = "cavium rng";
- rng->ops.read = cavium_rng_read;
- rng->ops.quality = 1000;
- pci_set_drvdata(pdev, rng);
- ret = hwrng_register(&rng->ops);
- if (ret) {
- dev_err(&pdev->dev, "Error registering device as HWRNG.\n");
- return ret;
- }
- return 0;
- }
- /* Remove the VF */
- void cavium_rng_remove_vf(struct pci_dev *pdev)
- {
- struct cavium_rng *rng;
- rng = pci_get_drvdata(pdev);
- hwrng_unregister(&rng->ops);
- }
- 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,
- .remove = cavium_rng_remove_vf,
- };
- module_pci_driver(cavium_rng_vf_driver);
- MODULE_AUTHOR("Omer Khaliq <okhaliq@caviumnetworks.com>");
- MODULE_LICENSE("GPL");
|