0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/clk.h>
0012 #include <linux/delay.h>
0013 #include <linux/hw_random.h>
0014 #include <linux/io.h>
0015 #include <linux/kernel.h>
0016 #include <linux/module.h>
0017 #include <linux/of.h>
0018 #include <linux/platform_device.h>
0019 #include <linux/slab.h>
0020
0021
0022 #define ST_RNG_STATUS_REG 0x20
0023 #define ST_RNG_DATA_REG 0x24
0024
0025
0026 #define ST_RNG_STATUS_BAD_SEQUENCE BIT(0)
0027 #define ST_RNG_STATUS_BAD_ALTERNANCE BIT(1)
0028 #define ST_RNG_STATUS_FIFO_FULL BIT(5)
0029
0030 #define ST_RNG_SAMPLE_SIZE 2
0031 #define ST_RNG_FIFO_DEPTH 4
0032 #define ST_RNG_FIFO_SIZE (ST_RNG_FIFO_DEPTH * ST_RNG_SAMPLE_SIZE)
0033
0034
0035
0036
0037
0038
0039
0040
0041 #define ST_RNG_FILL_FIFO_TIMEOUT (12 * 2)
0042
0043 struct st_rng_data {
0044 void __iomem *base;
0045 struct clk *clk;
0046 struct hwrng ops;
0047 };
0048
0049 static int st_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
0050 {
0051 struct st_rng_data *ddata = (struct st_rng_data *)rng->priv;
0052 u32 status;
0053 int i;
0054
0055
0056 for (i = 0; i < ST_RNG_FILL_FIFO_TIMEOUT; i++) {
0057 status = readl_relaxed(ddata->base + ST_RNG_STATUS_REG);
0058 if (status & ST_RNG_STATUS_FIFO_FULL)
0059 break;
0060 udelay(1);
0061 }
0062
0063 if (i == ST_RNG_FILL_FIFO_TIMEOUT)
0064 return 0;
0065
0066 for (i = 0; i < ST_RNG_FIFO_SIZE && i < max; i += 2)
0067 *(u16 *)(data + i) =
0068 readl_relaxed(ddata->base + ST_RNG_DATA_REG);
0069
0070 return i;
0071 }
0072
0073 static int st_rng_probe(struct platform_device *pdev)
0074 {
0075 struct st_rng_data *ddata;
0076 struct clk *clk;
0077 void __iomem *base;
0078 int ret;
0079
0080 ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
0081 if (!ddata)
0082 return -ENOMEM;
0083
0084 base = devm_platform_ioremap_resource(pdev, 0);
0085 if (IS_ERR(base))
0086 return PTR_ERR(base);
0087
0088 clk = devm_clk_get(&pdev->dev, NULL);
0089 if (IS_ERR(clk))
0090 return PTR_ERR(clk);
0091
0092 ret = clk_prepare_enable(clk);
0093 if (ret)
0094 return ret;
0095
0096 ddata->ops.priv = (unsigned long)ddata;
0097 ddata->ops.read = st_rng_read;
0098 ddata->ops.name = pdev->name;
0099 ddata->base = base;
0100 ddata->clk = clk;
0101
0102 dev_set_drvdata(&pdev->dev, ddata);
0103
0104 ret = devm_hwrng_register(&pdev->dev, &ddata->ops);
0105 if (ret) {
0106 dev_err(&pdev->dev, "Failed to register HW RNG\n");
0107 clk_disable_unprepare(clk);
0108 return ret;
0109 }
0110
0111 dev_info(&pdev->dev, "Successfully registered HW RNG\n");
0112
0113 return 0;
0114 }
0115
0116 static int st_rng_remove(struct platform_device *pdev)
0117 {
0118 struct st_rng_data *ddata = dev_get_drvdata(&pdev->dev);
0119
0120 clk_disable_unprepare(ddata->clk);
0121
0122 return 0;
0123 }
0124
0125 static const struct of_device_id st_rng_match[] __maybe_unused = {
0126 { .compatible = "st,rng" },
0127 {},
0128 };
0129 MODULE_DEVICE_TABLE(of, st_rng_match);
0130
0131 static struct platform_driver st_rng_driver = {
0132 .driver = {
0133 .name = "st-hwrandom",
0134 .of_match_table = of_match_ptr(st_rng_match),
0135 },
0136 .probe = st_rng_probe,
0137 .remove = st_rng_remove
0138 };
0139
0140 module_platform_driver(st_rng_driver);
0141
0142 MODULE_AUTHOR("Pankaj Dev <pankaj.dev@st.com>");
0143 MODULE_LICENSE("GPL v2");