Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1/*
  2 * Hardware Random Number Generator support for Cavium, Inc.
  3 * Thunder processor family.
  4 *
  5 * This file is subject to the terms and conditions of the GNU General Public
  6 * License.  See the file "COPYING" in the main directory of this archive
  7 * for more details.
  8 *
  9 * Copyright (C) 2016 Cavium, Inc.
 10 */
 11
 12#include <linux/hw_random.h>
 13#include <linux/io.h>
 14#include <linux/module.h>
 15#include <linux/pci.h>
 16#include <linux/pci_ids.h>
 17
 18struct cavium_rng {
 19	struct hwrng ops;
 20	void __iomem *result;
 21};
 22
 23/* Read data from the RNG unit */
 24static int cavium_rng_read(struct hwrng *rng, void *dat, size_t max, bool wait)
 25{
 26	struct cavium_rng *p = container_of(rng, struct cavium_rng, ops);
 27	unsigned int size = max;
 28
 29	while (size >= 8) {
 30		*((u64 *)dat) = readq(p->result);
 31		size -= 8;
 32		dat += 8;
 33	}
 34	while (size > 0) {
 35		*((u8 *)dat) = readb(p->result);
 36		size--;
 37		dat++;
 38	}
 39	return max;
 40}
 41
 42/* Map Cavium RNG to an HWRNG object */
 43static int cavium_rng_probe_vf(struct	pci_dev		*pdev,
 44			 const struct	pci_device_id	*id)
 45{
 46	struct	cavium_rng *rng;
 47	int	ret;
 48
 49	rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL);
 50	if (!rng)
 51		return -ENOMEM;
 52
 53	/* Map the RNG result */
 54	rng->result = pcim_iomap(pdev, 0, 0);
 55	if (!rng->result) {
 56		dev_err(&pdev->dev, "Error iomap failed retrieving result.\n");
 57		return -ENOMEM;
 58	}
 59
 60	rng->ops.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
 61				       "cavium-rng-%s", dev_name(&pdev->dev));
 62	if (!rng->ops.name)
 63		return -ENOMEM;
 64
 65	rng->ops.read    = cavium_rng_read;
 66	rng->ops.quality = 1000;
 67
 68	pci_set_drvdata(pdev, rng);
 69
 70	ret = hwrng_register(&rng->ops);
 71	if (ret) {
 72		dev_err(&pdev->dev, "Error registering device as HWRNG.\n");
 73		return ret;
 74	}
 75
 76	return 0;
 77}
 78
 79/* Remove the VF */
 80static void  cavium_rng_remove_vf(struct pci_dev *pdev)
 81{
 82	struct cavium_rng *rng;
 83
 84	rng = pci_get_drvdata(pdev);
 85	hwrng_unregister(&rng->ops);
 86}
 87
 88static const struct pci_device_id cavium_rng_vf_id_table[] = {
 89	{ PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 0xa033), 0, 0, 0},
 90	{0,},
 91};
 92MODULE_DEVICE_TABLE(pci, cavium_rng_vf_id_table);
 93
 94static struct pci_driver cavium_rng_vf_driver = {
 95	.name		= "cavium_rng_vf",
 96	.id_table	= cavium_rng_vf_id_table,
 97	.probe		= cavium_rng_probe_vf,
 98	.remove		= cavium_rng_remove_vf,
 99};
100module_pci_driver(cavium_rng_vf_driver);
101
102MODULE_AUTHOR("Omer Khaliq <okhaliq@caviumnetworks.com>");
103MODULE_LICENSE("GPL");