0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/hw_random.h>
0010 #include <linux/io.h>
0011 #include <linux/module.h>
0012 #include <linux/pci.h>
0013 #include <linux/pci_ids.h>
0014
0015 #include <asm/arch_timer.h>
0016
0017
0018 #define PCI_DEVID_CAVIUM_RNG_PF 0xA018
0019 #define PCI_DEVID_CAVIUM_RNG_VF 0xA033
0020
0021 #define HEALTH_STATUS_REG 0x38
0022
0023
0024 #define PCI_DEVICE_ID_RST_OTX2 0xA085
0025 #define RST_BOOT_REG 0x1600ULL
0026 #define CLOCK_BASE_RATE 50000000ULL
0027 #define MSEC_TO_NSEC(x) (x * 1000000)
0028
0029 struct cavium_rng {
0030 struct hwrng ops;
0031 void __iomem *result;
0032 void __iomem *pf_regbase;
0033 struct pci_dev *pdev;
0034 u64 clock_rate;
0035 u64 prev_error;
0036 u64 prev_time;
0037 };
0038
0039 static inline bool is_octeontx(struct pci_dev *pdev)
0040 {
0041 if (midr_is_cpu_model_range(read_cpuid_id(), MIDR_THUNDERX_83XX,
0042 MIDR_CPU_VAR_REV(0, 0),
0043 MIDR_CPU_VAR_REV(3, 0)) ||
0044 midr_is_cpu_model_range(read_cpuid_id(), MIDR_THUNDERX_81XX,
0045 MIDR_CPU_VAR_REV(0, 0),
0046 MIDR_CPU_VAR_REV(3, 0)) ||
0047 midr_is_cpu_model_range(read_cpuid_id(), MIDR_THUNDERX,
0048 MIDR_CPU_VAR_REV(0, 0),
0049 MIDR_CPU_VAR_REV(3, 0)))
0050 return true;
0051
0052 return false;
0053 }
0054
0055 static u64 rng_get_coprocessor_clkrate(void)
0056 {
0057 u64 ret = CLOCK_BASE_RATE * 16;
0058 struct pci_dev *pdev;
0059 void __iomem *base;
0060
0061 pdev = pci_get_device(PCI_VENDOR_ID_CAVIUM,
0062 PCI_DEVICE_ID_RST_OTX2, NULL);
0063 if (!pdev)
0064 goto error;
0065
0066 base = pci_ioremap_bar(pdev, 0);
0067 if (!base)
0068 goto error_put_pdev;
0069
0070
0071 ret = CLOCK_BASE_RATE * ((readq(base + RST_BOOT_REG) >> 33) & 0x3F);
0072
0073 iounmap(base);
0074
0075 error_put_pdev:
0076 pci_dev_put(pdev);
0077
0078 error:
0079 return ret;
0080 }
0081
0082 static int check_rng_health(struct cavium_rng *rng)
0083 {
0084 u64 cur_err, cur_time;
0085 u64 status, cycles;
0086 u64 time_elapsed;
0087
0088
0089
0090 if (!rng->pf_regbase)
0091 return 0;
0092
0093 status = readq(rng->pf_regbase + HEALTH_STATUS_REG);
0094 if (status & BIT_ULL(0)) {
0095 dev_err(&rng->pdev->dev, "HWRNG: Startup health test failed\n");
0096 return -EIO;
0097 }
0098
0099 cycles = status >> 1;
0100 if (!cycles)
0101 return 0;
0102
0103 cur_time = arch_timer_read_counter();
0104
0105
0106
0107
0108
0109 cycles = cycles / 2;
0110 cur_err = (cycles * 1000000000) / rng->clock_rate;
0111
0112
0113
0114
0115 if (cur_err > MSEC_TO_NSEC(10)) {
0116 rng->prev_error = 0;
0117 rng->prev_time = 0;
0118 return 0;
0119 }
0120
0121 if (rng->prev_error) {
0122
0123
0124
0125 time_elapsed = (cur_time - rng->prev_time) * 10;
0126 time_elapsed += rng->prev_error;
0127
0128
0129
0130
0131
0132 if (cur_err < time_elapsed) {
0133 dev_err(&rng->pdev->dev, "HWRNG failure detected\n");
0134 rng->prev_error = cur_err;
0135 rng->prev_time = cur_time;
0136 return -EIO;
0137 }
0138 }
0139
0140 rng->prev_error = cur_err;
0141 rng->prev_time = cur_time;
0142 return 0;
0143 }
0144
0145
0146 static int cavium_rng_read(struct hwrng *rng, void *dat, size_t max, bool wait)
0147 {
0148 struct cavium_rng *p = container_of(rng, struct cavium_rng, ops);
0149 unsigned int size = max;
0150 int err = 0;
0151
0152 err = check_rng_health(p);
0153 if (err)
0154 return err;
0155
0156 while (size >= 8) {
0157 *((u64 *)dat) = readq(p->result);
0158 size -= 8;
0159 dat += 8;
0160 }
0161 while (size > 0) {
0162 *((u8 *)dat) = readb(p->result);
0163 size--;
0164 dat++;
0165 }
0166 return max;
0167 }
0168
0169 static int cavium_map_pf_regs(struct cavium_rng *rng)
0170 {
0171 struct pci_dev *pdev;
0172
0173
0174 if (is_octeontx(rng->pdev)) {
0175 rng->pf_regbase = NULL;
0176 return 0;
0177 }
0178
0179 pdev = pci_get_device(PCI_VENDOR_ID_CAVIUM,
0180 PCI_DEVID_CAVIUM_RNG_PF, NULL);
0181 if (!pdev) {
0182 pr_err("Cannot find RNG PF device\n");
0183 return -EIO;
0184 }
0185
0186 rng->pf_regbase = ioremap(pci_resource_start(pdev, 0),
0187 pci_resource_len(pdev, 0));
0188 if (!rng->pf_regbase) {
0189 dev_err(&pdev->dev, "Failed to map PF CSR region\n");
0190 pci_dev_put(pdev);
0191 return -ENOMEM;
0192 }
0193
0194 pci_dev_put(pdev);
0195
0196
0197 rng->clock_rate = rng_get_coprocessor_clkrate();
0198
0199 return 0;
0200 }
0201
0202
0203 static int cavium_rng_probe_vf(struct pci_dev *pdev,
0204 const struct pci_device_id *id)
0205 {
0206 struct cavium_rng *rng;
0207 int ret;
0208
0209 rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL);
0210 if (!rng)
0211 return -ENOMEM;
0212
0213 rng->pdev = pdev;
0214
0215
0216 rng->result = pcim_iomap(pdev, 0, 0);
0217 if (!rng->result) {
0218 dev_err(&pdev->dev, "Error iomap failed retrieving result.\n");
0219 return -ENOMEM;
0220 }
0221
0222 rng->ops.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
0223 "cavium-rng-%s", dev_name(&pdev->dev));
0224 if (!rng->ops.name)
0225 return -ENOMEM;
0226
0227 rng->ops.read = cavium_rng_read;
0228 rng->ops.quality = 1000;
0229
0230 pci_set_drvdata(pdev, rng);
0231
0232
0233 ret = cavium_map_pf_regs(rng);
0234 if (ret)
0235 return ret;
0236
0237 ret = devm_hwrng_register(&pdev->dev, &rng->ops);
0238 if (ret) {
0239 dev_err(&pdev->dev, "Error registering device as HWRNG.\n");
0240 return ret;
0241 }
0242
0243 return 0;
0244 }
0245
0246
0247 static void cavium_rng_remove_vf(struct pci_dev *pdev)
0248 {
0249 struct cavium_rng *rng;
0250
0251 rng = pci_get_drvdata(pdev);
0252 iounmap(rng->pf_regbase);
0253 }
0254
0255 static const struct pci_device_id cavium_rng_vf_id_table[] = {
0256 { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CAVIUM_RNG_VF) },
0257 { 0, }
0258 };
0259 MODULE_DEVICE_TABLE(pci, cavium_rng_vf_id_table);
0260
0261 static struct pci_driver cavium_rng_vf_driver = {
0262 .name = "cavium_rng_vf",
0263 .id_table = cavium_rng_vf_id_table,
0264 .probe = cavium_rng_probe_vf,
0265 .remove = cavium_rng_remove_vf,
0266 };
0267 module_pci_driver(cavium_rng_vf_driver);
0268
0269 MODULE_AUTHOR("Omer Khaliq <okhaliq@caviumnetworks.com>");
0270 MODULE_LICENSE("GPL v2");