1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Hardware Random Number Generator support. |
4 | * Cavium Thunder, Marvell OcteonTx/Tx2 processor families. |
5 | * |
6 | * Copyright (C) 2016 Cavium, Inc. |
7 | */ |
8 | |
9 | #include <linux/hw_random.h> |
10 | #include <linux/io.h> |
11 | #include <linux/module.h> |
12 | #include <linux/pci.h> |
13 | #include <linux/pci_ids.h> |
14 | |
15 | #define THUNDERX_RNM_ENT_EN 0x1 |
16 | #define THUNDERX_RNM_RNG_EN 0x2 |
17 | |
18 | struct cavium_rng_pf { |
19 | void __iomem *control_status; |
20 | }; |
21 | |
22 | /* Enable the RNG hardware and activate the VF */ |
23 | static int cavium_rng_probe(struct pci_dev *pdev, |
24 | const struct pci_device_id *id) |
25 | { |
26 | struct cavium_rng_pf *rng; |
27 | int iov_err; |
28 | |
29 | rng = devm_kzalloc(dev: &pdev->dev, size: sizeof(*rng), GFP_KERNEL); |
30 | if (!rng) |
31 | return -ENOMEM; |
32 | |
33 | /*Map the RNG control */ |
34 | rng->control_status = pcim_iomap(pdev, bar: 0, maxlen: 0); |
35 | if (!rng->control_status) { |
36 | dev_err(&pdev->dev, |
37 | "Error iomap failed retrieving control_status.\n" ); |
38 | return -ENOMEM; |
39 | } |
40 | |
41 | /* Enable the RNG hardware and entropy source */ |
42 | writeq(THUNDERX_RNM_RNG_EN | THUNDERX_RNM_ENT_EN, |
43 | addr: rng->control_status); |
44 | |
45 | pci_set_drvdata(pdev, data: rng); |
46 | |
47 | /* Enable the Cavium RNG as a VF */ |
48 | iov_err = pci_enable_sriov(dev: pdev, nr_virtfn: 1); |
49 | if (iov_err != 0) { |
50 | /* Disable the RNG hardware and entropy source */ |
51 | writeq(val: 0, addr: rng->control_status); |
52 | dev_err(&pdev->dev, |
53 | "Error initializing RNG virtual function,(%i).\n" , |
54 | iov_err); |
55 | return iov_err; |
56 | } |
57 | |
58 | return 0; |
59 | } |
60 | |
61 | /* Disable VF and RNG Hardware */ |
62 | static void cavium_rng_remove(struct pci_dev *pdev) |
63 | { |
64 | struct cavium_rng_pf *rng; |
65 | |
66 | rng = pci_get_drvdata(pdev); |
67 | |
68 | /* Remove the VF */ |
69 | pci_disable_sriov(dev: pdev); |
70 | |
71 | /* Disable the RNG hardware and entropy source */ |
72 | writeq(val: 0, addr: rng->control_status); |
73 | } |
74 | |
75 | static const struct pci_device_id cavium_rng_pf_id_table[] = { |
76 | { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 0xa018), 0, 0, 0}, /* Thunder RNM */ |
77 | {0,}, |
78 | }; |
79 | |
80 | MODULE_DEVICE_TABLE(pci, cavium_rng_pf_id_table); |
81 | |
82 | static struct pci_driver cavium_rng_pf_driver = { |
83 | .name = "cavium_rng_pf" , |
84 | .id_table = cavium_rng_pf_id_table, |
85 | .probe = cavium_rng_probe, |
86 | .remove = cavium_rng_remove, |
87 | }; |
88 | |
89 | module_pci_driver(cavium_rng_pf_driver); |
90 | MODULE_AUTHOR("Omer Khaliq <okhaliq@caviumnetworks.com>" ); |
91 | MODULE_LICENSE("GPL v2" ); |
92 | |