0001
0002
0003
0004 #include <linux/kernel.h>
0005 #include <linux/module.h>
0006 #include <linux/mod_devicetable.h>
0007 #include <linux/err.h>
0008 #include <linux/io.h>
0009 #include <linux/hw_random.h>
0010 #include <linux/of_device.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/delay.h>
0013
0014 #define CONTROL_REG 0x00000000
0015 #define STATUS_REG 0x00000004
0016 #define RAND_REG 0x00000000
0017
0018 #define HOST_TO_TRNG_RESET 0x00000001
0019 #define HOST_TO_TRNG_RELEASE_RESET 0x00000002
0020 #define HOST_TO_TRNG_ENABLE 0x80000000
0021 #define HOST_TO_TRNG_ZEROIZE 0x80000004
0022 #define HOST_TO_TRNG_ACK_ZEROIZE 0x80000008
0023 #define HOST_TO_TRNG_READ 0x8000000F
0024
0025
0026 #define TRNG_ACK_RESET 0x000000AC
0027 #define TRNG_SUCCESSFUL_STARTUP 0x00000057
0028 #define TRNG_FAILED_STARTUP 0x000000FA
0029 #define TRNG_NEW_RAND_AVAILABLE 0x000000ED
0030
0031 struct xiphera_trng {
0032 void __iomem *mem;
0033 struct hwrng rng;
0034 };
0035
0036 static int xiphera_trng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
0037 {
0038 struct xiphera_trng *trng = container_of(rng, struct xiphera_trng, rng);
0039 int ret = 0;
0040
0041 while (max >= sizeof(u32)) {
0042
0043 if (readl(trng->mem + STATUS_REG) == TRNG_NEW_RAND_AVAILABLE) {
0044 *(u32 *)buf = readl(trng->mem + RAND_REG);
0045
0046
0047
0048
0049 writel(HOST_TO_TRNG_READ, trng->mem + CONTROL_REG);
0050 writel(HOST_TO_TRNG_ENABLE, trng->mem + CONTROL_REG);
0051 ret += sizeof(u32);
0052 buf += sizeof(u32);
0053 max -= sizeof(u32);
0054 } else {
0055 break;
0056 }
0057 }
0058 return ret;
0059 }
0060
0061 static int xiphera_trng_probe(struct platform_device *pdev)
0062 {
0063 int ret;
0064 struct xiphera_trng *trng;
0065 struct device *dev = &pdev->dev;
0066
0067 trng = devm_kzalloc(dev, sizeof(*trng), GFP_KERNEL);
0068 if (!trng)
0069 return -ENOMEM;
0070
0071 trng->mem = devm_platform_ioremap_resource(pdev, 0);
0072 if (IS_ERR(trng->mem))
0073 return PTR_ERR(trng->mem);
0074
0075
0076
0077
0078
0079 writel(HOST_TO_TRNG_RESET, trng->mem + CONTROL_REG);
0080 usleep_range(100, 200);
0081
0082 if (readl(trng->mem + STATUS_REG) != TRNG_ACK_RESET) {
0083
0084
0085
0086
0087 usleep_range(100, 200);
0088 if (readl(trng->mem + STATUS_REG) != TRNG_ACK_RESET) {
0089 dev_err(dev, "failed to reset the trng ip\n");
0090 return -ENODEV;
0091 }
0092 }
0093
0094
0095
0096
0097
0098 writel(HOST_TO_TRNG_RELEASE_RESET, trng->mem + CONTROL_REG);
0099 writel(HOST_TO_TRNG_ENABLE, trng->mem + CONTROL_REG);
0100 writel(HOST_TO_TRNG_ZEROIZE, trng->mem + CONTROL_REG);
0101 msleep(20);
0102
0103 if (readl(trng->mem + STATUS_REG) != TRNG_SUCCESSFUL_STARTUP) {
0104
0105 if (readl(trng->mem + STATUS_REG) == TRNG_FAILED_STARTUP) {
0106 dev_err(dev, "trng ip startup-tests failed\n");
0107 return -ENODEV;
0108 }
0109 dev_err(dev, "startup-tests yielded no response\n");
0110 return -ENODEV;
0111 }
0112
0113 writel(HOST_TO_TRNG_ACK_ZEROIZE, trng->mem + CONTROL_REG);
0114
0115 trng->rng.name = pdev->name;
0116 trng->rng.read = xiphera_trng_read;
0117 trng->rng.quality = 900;
0118
0119 ret = devm_hwrng_register(dev, &trng->rng);
0120 if (ret) {
0121 dev_err(dev, "failed to register rng device: %d\n", ret);
0122 return ret;
0123 }
0124
0125 platform_set_drvdata(pdev, trng);
0126
0127 return 0;
0128 }
0129
0130 static const struct of_device_id xiphera_trng_of_match[] = {
0131 { .compatible = "xiphera,xip8001b-trng", },
0132 {},
0133 };
0134 MODULE_DEVICE_TABLE(of, xiphera_trng_of_match);
0135
0136 static struct platform_driver xiphera_trng_driver = {
0137 .driver = {
0138 .name = "xiphera-trng",
0139 .of_match_table = xiphera_trng_of_match,
0140 },
0141 .probe = xiphera_trng_probe,
0142 };
0143
0144 module_platform_driver(xiphera_trng_driver);
0145
0146 MODULE_LICENSE("GPL");
0147 MODULE_AUTHOR("Atte Tommiska");
0148 MODULE_DESCRIPTION("Xiphera FPGA-based true random number generator driver");