0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #include <linux/completion.h>
0021 #include <linux/delay.h>
0022 #include <linux/hrtimer.h>
0023 #include <linux/hw_random.h>
0024 #include <linux/io.h>
0025 #include <linux/ktime.h>
0026 #include <linux/module.h>
0027 #include <linux/of.h>
0028 #include <linux/platform_device.h>
0029 #include <linux/slab.h>
0030 #include <linux/time.h>
0031 #include <linux/timeriomem-rng.h>
0032
0033 struct timeriomem_rng_private {
0034 void __iomem *io_base;
0035 ktime_t period;
0036 unsigned int present:1;
0037
0038 struct hrtimer timer;
0039 struct completion completion;
0040
0041 struct hwrng rng_ops;
0042 };
0043
0044 static int timeriomem_rng_read(struct hwrng *hwrng, void *data,
0045 size_t max, bool wait)
0046 {
0047 struct timeriomem_rng_private *priv =
0048 container_of(hwrng, struct timeriomem_rng_private, rng_ops);
0049 int retval = 0;
0050 int period_us = ktime_to_us(priv->period);
0051
0052
0053
0054
0055
0056
0057
0058 if (!wait && !priv->present)
0059 return 0;
0060
0061 wait_for_completion(&priv->completion);
0062
0063 do {
0064
0065
0066
0067
0068
0069
0070 if (retval > 0)
0071 usleep_range(period_us,
0072 period_us + max(1, period_us / 100));
0073
0074 *(u32 *)data = readl(priv->io_base);
0075 retval += sizeof(u32);
0076 data += sizeof(u32);
0077 max -= sizeof(u32);
0078 } while (wait && max > sizeof(u32));
0079
0080
0081
0082
0083
0084 priv->present = 0;
0085 reinit_completion(&priv->completion);
0086 hrtimer_forward_now(&priv->timer, priv->period);
0087 hrtimer_restart(&priv->timer);
0088
0089 return retval;
0090 }
0091
0092 static enum hrtimer_restart timeriomem_rng_trigger(struct hrtimer *timer)
0093 {
0094 struct timeriomem_rng_private *priv
0095 = container_of(timer, struct timeriomem_rng_private, timer);
0096
0097 priv->present = 1;
0098 complete(&priv->completion);
0099
0100 return HRTIMER_NORESTART;
0101 }
0102
0103 static int timeriomem_rng_probe(struct platform_device *pdev)
0104 {
0105 struct timeriomem_rng_data *pdata = pdev->dev.platform_data;
0106 struct timeriomem_rng_private *priv;
0107 struct resource *res;
0108 int err = 0;
0109 int period;
0110
0111 if (!pdev->dev.of_node && !pdata) {
0112 dev_err(&pdev->dev, "timeriomem_rng_data is missing\n");
0113 return -EINVAL;
0114 }
0115
0116 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0117 if (!res)
0118 return -ENXIO;
0119
0120 if (res->start % 4 != 0 || resource_size(res) < 4) {
0121 dev_err(&pdev->dev,
0122 "address must be at least four bytes wide and 32-bit aligned\n");
0123 return -EINVAL;
0124 }
0125
0126
0127 priv = devm_kzalloc(&pdev->dev,
0128 sizeof(struct timeriomem_rng_private), GFP_KERNEL);
0129 if (!priv)
0130 return -ENOMEM;
0131
0132 platform_set_drvdata(pdev, priv);
0133
0134 if (pdev->dev.of_node) {
0135 int i;
0136
0137 if (!of_property_read_u32(pdev->dev.of_node,
0138 "period", &i))
0139 period = i;
0140 else {
0141 dev_err(&pdev->dev, "missing period\n");
0142 return -EINVAL;
0143 }
0144
0145 if (!of_property_read_u32(pdev->dev.of_node,
0146 "quality", &i))
0147 priv->rng_ops.quality = i;
0148 else
0149 priv->rng_ops.quality = 0;
0150 } else {
0151 period = pdata->period;
0152 priv->rng_ops.quality = pdata->quality;
0153 }
0154
0155 priv->period = ns_to_ktime(period * NSEC_PER_USEC);
0156 init_completion(&priv->completion);
0157 hrtimer_init(&priv->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
0158 priv->timer.function = timeriomem_rng_trigger;
0159
0160 priv->rng_ops.name = dev_name(&pdev->dev);
0161 priv->rng_ops.read = timeriomem_rng_read;
0162
0163 priv->io_base = devm_ioremap_resource(&pdev->dev, res);
0164 if (IS_ERR(priv->io_base)) {
0165 return PTR_ERR(priv->io_base);
0166 }
0167
0168
0169 priv->present = 1;
0170 complete(&priv->completion);
0171
0172 err = devm_hwrng_register(&pdev->dev, &priv->rng_ops);
0173 if (err) {
0174 dev_err(&pdev->dev, "problem registering\n");
0175 return err;
0176 }
0177
0178 dev_info(&pdev->dev, "32bits from 0x%p @ %dus\n",
0179 priv->io_base, period);
0180
0181 return 0;
0182 }
0183
0184 static int timeriomem_rng_remove(struct platform_device *pdev)
0185 {
0186 struct timeriomem_rng_private *priv = platform_get_drvdata(pdev);
0187
0188 hrtimer_cancel(&priv->timer);
0189
0190 return 0;
0191 }
0192
0193 static const struct of_device_id timeriomem_rng_match[] = {
0194 { .compatible = "timeriomem_rng" },
0195 {},
0196 };
0197 MODULE_DEVICE_TABLE(of, timeriomem_rng_match);
0198
0199 static struct platform_driver timeriomem_rng_driver = {
0200 .driver = {
0201 .name = "timeriomem_rng",
0202 .of_match_table = timeriomem_rng_match,
0203 },
0204 .probe = timeriomem_rng_probe,
0205 .remove = timeriomem_rng_remove,
0206 };
0207
0208 module_platform_driver(timeriomem_rng_driver);
0209
0210 MODULE_LICENSE("GPL");
0211 MODULE_AUTHOR("Alexander Clouter <alex@digriz.org.uk>");
0212 MODULE_DESCRIPTION("Timer IOMEM H/W RNG driver");