|  | // SPDX-License-Identifier: GPL-2.0 | 
|  | /* | 
|  | * Hardware Random Number Generator support. | 
|  | * Cavium Thunder, Marvell OcteonTx/Tx2 processor families. | 
|  | * | 
|  | * 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> | 
|  |  | 
|  | #define THUNDERX_RNM_ENT_EN     0x1 | 
|  | #define THUNDERX_RNM_RNG_EN     0x2 | 
|  |  | 
|  | struct cavium_rng_pf { | 
|  | void __iomem *control_status; | 
|  | }; | 
|  |  | 
|  | /* Enable the RNG hardware and activate the VF */ | 
|  | static int cavium_rng_probe(struct pci_dev *pdev, | 
|  | const struct pci_device_id *id) | 
|  | { | 
|  | struct	cavium_rng_pf *rng; | 
|  | int	iov_err; | 
|  |  | 
|  | rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL); | 
|  | if (!rng) | 
|  | return -ENOMEM; | 
|  |  | 
|  | /*Map the RNG control */ | 
|  | rng->control_status = pcim_iomap(pdev, 0, 0); | 
|  | if (!rng->control_status) { | 
|  | dev_err(&pdev->dev, | 
|  | "Error iomap failed retrieving control_status.\n"); | 
|  | return -ENOMEM; | 
|  | } | 
|  |  | 
|  | /* Enable the RNG hardware and entropy source */ | 
|  | writeq(THUNDERX_RNM_RNG_EN | THUNDERX_RNM_ENT_EN, | 
|  | rng->control_status); | 
|  |  | 
|  | pci_set_drvdata(pdev, rng); | 
|  |  | 
|  | /* Enable the Cavium RNG as a VF */ | 
|  | iov_err = pci_enable_sriov(pdev, 1); | 
|  | if (iov_err != 0) { | 
|  | /* Disable the RNG hardware and entropy source */ | 
|  | writeq(0, rng->control_status); | 
|  | dev_err(&pdev->dev, | 
|  | "Error initializing RNG virtual function,(%i).\n", | 
|  | iov_err); | 
|  | return iov_err; | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /* Disable VF and RNG Hardware */ | 
|  | static void cavium_rng_remove(struct pci_dev *pdev) | 
|  | { | 
|  | struct cavium_rng_pf *rng; | 
|  |  | 
|  | rng = pci_get_drvdata(pdev); | 
|  |  | 
|  | /* Remove the VF */ | 
|  | pci_disable_sriov(pdev); | 
|  |  | 
|  | /* Disable the RNG hardware and entropy source */ | 
|  | writeq(0, rng->control_status); | 
|  | } | 
|  |  | 
|  | static const struct pci_device_id cavium_rng_pf_id_table[] = { | 
|  | { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 0xa018), 0, 0, 0}, /* Thunder RNM */ | 
|  | {0,}, | 
|  | }; | 
|  |  | 
|  | MODULE_DEVICE_TABLE(pci, cavium_rng_pf_id_table); | 
|  |  | 
|  | static struct pci_driver cavium_rng_pf_driver = { | 
|  | .name		= "cavium_rng_pf", | 
|  | .id_table	= cavium_rng_pf_id_table, | 
|  | .probe		= cavium_rng_probe, | 
|  | .remove		= cavium_rng_remove, | 
|  | }; | 
|  |  | 
|  | module_pci_driver(cavium_rng_pf_driver); | 
|  | MODULE_AUTHOR("Omer Khaliq <okhaliq@caviumnetworks.com>"); | 
|  | MODULE_DESCRIPTION("Cavium ThunderX Random Number Generator support"); | 
|  | MODULE_LICENSE("GPL v2"); |