Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/char/hw_random/omap-rng.c
29269 views
1
/*
2
* omap-rng.c - RNG driver for TI OMAP CPU family
3
*
4
* Author: Deepak Saxena <[email protected]>
5
*
6
* Copyright 2005 (c) MontaVista Software, Inc.
7
*
8
* Mostly based on original driver:
9
*
10
* Copyright (C) 2005 Nokia Corporation
11
* Author: Juha Yrjölä <[email protected]>
12
*
13
* This file is licensed under the terms of the GNU General Public
14
* License version 2. This program is licensed "as is" without any
15
* warranty of any kind, whether express or implied.
16
*/
17
18
#include <linux/module.h>
19
#include <linux/init.h>
20
#include <linux/random.h>
21
#include <linux/err.h>
22
#include <linux/platform_device.h>
23
#include <linux/hw_random.h>
24
#include <linux/delay.h>
25
#include <linux/kernel.h>
26
#include <linux/slab.h>
27
#include <linux/pm_runtime.h>
28
#include <linux/of.h>
29
#include <linux/interrupt.h>
30
#include <linux/clk.h>
31
#include <linux/io.h>
32
33
#define RNG_REG_STATUS_RDY (1 << 0)
34
35
#define RNG_REG_INTACK_RDY_MASK (1 << 0)
36
#define RNG_REG_INTACK_SHUTDOWN_OFLO_MASK (1 << 1)
37
#define RNG_SHUTDOWN_OFLO_MASK (1 << 1)
38
39
#define RNG_CONTROL_STARTUP_CYCLES_SHIFT 16
40
#define RNG_CONTROL_STARTUP_CYCLES_MASK (0xffff << 16)
41
#define RNG_CONTROL_ENABLE_TRNG_SHIFT 10
42
#define RNG_CONTROL_ENABLE_TRNG_MASK (1 << 10)
43
44
#define RNG_CONFIG_MAX_REFIL_CYCLES_SHIFT 16
45
#define RNG_CONFIG_MAX_REFIL_CYCLES_MASK (0xffff << 16)
46
#define RNG_CONFIG_MIN_REFIL_CYCLES_SHIFT 0
47
#define RNG_CONFIG_MIN_REFIL_CYCLES_MASK (0xff << 0)
48
49
#define RNG_CONTROL_STARTUP_CYCLES 0xff
50
#define RNG_CONFIG_MIN_REFIL_CYCLES 0x21
51
#define RNG_CONFIG_MAX_REFIL_CYCLES 0x22
52
53
#define RNG_ALARMCNT_ALARM_TH_SHIFT 0x0
54
#define RNG_ALARMCNT_ALARM_TH_MASK (0xff << 0)
55
#define RNG_ALARMCNT_SHUTDOWN_TH_SHIFT 16
56
#define RNG_ALARMCNT_SHUTDOWN_TH_MASK (0x1f << 16)
57
#define RNG_ALARM_THRESHOLD 0xff
58
#define RNG_SHUTDOWN_THRESHOLD 0x4
59
60
#define RNG_REG_FROENABLE_MASK 0xffffff
61
#define RNG_REG_FRODETUNE_MASK 0xffffff
62
63
#define OMAP2_RNG_OUTPUT_SIZE 0x4
64
#define OMAP4_RNG_OUTPUT_SIZE 0x8
65
#define EIP76_RNG_OUTPUT_SIZE 0x10
66
67
/*
68
* EIP76 RNG takes approx. 700us to produce 16 bytes of output data
69
* as per testing results. And to account for the lack of udelay()'s
70
* reliability, we keep the timeout as 1000us.
71
*/
72
#define RNG_DATA_FILL_TIMEOUT 100
73
74
enum {
75
RNG_OUTPUT_0_REG = 0,
76
RNG_OUTPUT_1_REG,
77
RNG_OUTPUT_2_REG,
78
RNG_OUTPUT_3_REG,
79
RNG_STATUS_REG,
80
RNG_INTMASK_REG,
81
RNG_INTACK_REG,
82
RNG_CONTROL_REG,
83
RNG_CONFIG_REG,
84
RNG_ALARMCNT_REG,
85
RNG_FROENABLE_REG,
86
RNG_FRODETUNE_REG,
87
RNG_ALARMMASK_REG,
88
RNG_ALARMSTOP_REG,
89
RNG_REV_REG,
90
RNG_SYSCONFIG_REG,
91
};
92
93
static const u16 reg_map_omap2[] = {
94
[RNG_OUTPUT_0_REG] = 0x0,
95
[RNG_STATUS_REG] = 0x4,
96
[RNG_CONFIG_REG] = 0x28,
97
[RNG_REV_REG] = 0x3c,
98
[RNG_SYSCONFIG_REG] = 0x40,
99
};
100
101
static const u16 reg_map_omap4[] = {
102
[RNG_OUTPUT_0_REG] = 0x0,
103
[RNG_OUTPUT_1_REG] = 0x4,
104
[RNG_STATUS_REG] = 0x8,
105
[RNG_INTMASK_REG] = 0xc,
106
[RNG_INTACK_REG] = 0x10,
107
[RNG_CONTROL_REG] = 0x14,
108
[RNG_CONFIG_REG] = 0x18,
109
[RNG_ALARMCNT_REG] = 0x1c,
110
[RNG_FROENABLE_REG] = 0x20,
111
[RNG_FRODETUNE_REG] = 0x24,
112
[RNG_ALARMMASK_REG] = 0x28,
113
[RNG_ALARMSTOP_REG] = 0x2c,
114
[RNG_REV_REG] = 0x1FE0,
115
[RNG_SYSCONFIG_REG] = 0x1FE4,
116
};
117
118
static const u16 reg_map_eip76[] = {
119
[RNG_OUTPUT_0_REG] = 0x0,
120
[RNG_OUTPUT_1_REG] = 0x4,
121
[RNG_OUTPUT_2_REG] = 0x8,
122
[RNG_OUTPUT_3_REG] = 0xc,
123
[RNG_STATUS_REG] = 0x10,
124
[RNG_INTACK_REG] = 0x10,
125
[RNG_CONTROL_REG] = 0x14,
126
[RNG_CONFIG_REG] = 0x18,
127
[RNG_ALARMCNT_REG] = 0x1c,
128
[RNG_FROENABLE_REG] = 0x20,
129
[RNG_FRODETUNE_REG] = 0x24,
130
[RNG_ALARMMASK_REG] = 0x28,
131
[RNG_ALARMSTOP_REG] = 0x2c,
132
[RNG_REV_REG] = 0x7c,
133
};
134
135
struct omap_rng_dev;
136
/**
137
* struct omap_rng_pdata - RNG IP block-specific data
138
* @regs: Pointer to the register offsets structure.
139
* @data_size: No. of bytes in RNG output.
140
* @data_present: Callback to determine if data is available.
141
* @init: Callback for IP specific initialization sequence.
142
* @cleanup: Callback for IP specific cleanup sequence.
143
*/
144
struct omap_rng_pdata {
145
u16 *regs;
146
u32 data_size;
147
u32 (*data_present)(struct omap_rng_dev *priv);
148
int (*init)(struct omap_rng_dev *priv);
149
void (*cleanup)(struct omap_rng_dev *priv);
150
};
151
152
struct omap_rng_dev {
153
void __iomem *base;
154
struct device *dev;
155
const struct omap_rng_pdata *pdata;
156
struct hwrng rng;
157
struct clk *clk;
158
struct clk *clk_reg;
159
};
160
161
static inline u32 omap_rng_read(struct omap_rng_dev *priv, u16 reg)
162
{
163
return __raw_readl(priv->base + priv->pdata->regs[reg]);
164
}
165
166
static inline void omap_rng_write(struct omap_rng_dev *priv, u16 reg,
167
u32 val)
168
{
169
__raw_writel(val, priv->base + priv->pdata->regs[reg]);
170
}
171
172
173
static int omap_rng_do_read(struct hwrng *rng, void *data, size_t max,
174
bool wait)
175
{
176
struct omap_rng_dev *priv;
177
int i, present;
178
179
priv = (struct omap_rng_dev *)rng->priv;
180
181
if (max < priv->pdata->data_size)
182
return 0;
183
184
for (i = 0; i < RNG_DATA_FILL_TIMEOUT; i++) {
185
present = priv->pdata->data_present(priv);
186
if (present || !wait)
187
break;
188
189
udelay(10);
190
}
191
if (!present)
192
return 0;
193
194
memcpy_fromio(data, priv->base + priv->pdata->regs[RNG_OUTPUT_0_REG],
195
priv->pdata->data_size);
196
197
if (priv->pdata->regs[RNG_INTACK_REG])
198
omap_rng_write(priv, RNG_INTACK_REG, RNG_REG_INTACK_RDY_MASK);
199
200
return priv->pdata->data_size;
201
}
202
203
static int omap_rng_init(struct hwrng *rng)
204
{
205
struct omap_rng_dev *priv;
206
207
priv = (struct omap_rng_dev *)rng->priv;
208
return priv->pdata->init(priv);
209
}
210
211
static void omap_rng_cleanup(struct hwrng *rng)
212
{
213
struct omap_rng_dev *priv;
214
215
priv = (struct omap_rng_dev *)rng->priv;
216
priv->pdata->cleanup(priv);
217
}
218
219
220
static inline u32 omap2_rng_data_present(struct omap_rng_dev *priv)
221
{
222
return omap_rng_read(priv, RNG_STATUS_REG) ? 0 : 1;
223
}
224
225
static int omap2_rng_init(struct omap_rng_dev *priv)
226
{
227
omap_rng_write(priv, RNG_SYSCONFIG_REG, 0x1);
228
return 0;
229
}
230
231
static void omap2_rng_cleanup(struct omap_rng_dev *priv)
232
{
233
omap_rng_write(priv, RNG_SYSCONFIG_REG, 0x0);
234
}
235
236
static struct omap_rng_pdata omap2_rng_pdata = {
237
.regs = (u16 *)reg_map_omap2,
238
.data_size = OMAP2_RNG_OUTPUT_SIZE,
239
.data_present = omap2_rng_data_present,
240
.init = omap2_rng_init,
241
.cleanup = omap2_rng_cleanup,
242
};
243
244
static inline u32 omap4_rng_data_present(struct omap_rng_dev *priv)
245
{
246
return omap_rng_read(priv, RNG_STATUS_REG) & RNG_REG_STATUS_RDY;
247
}
248
249
static int eip76_rng_init(struct omap_rng_dev *priv)
250
{
251
u32 val;
252
253
/* Return if RNG is already running. */
254
if (omap_rng_read(priv, RNG_CONTROL_REG) & RNG_CONTROL_ENABLE_TRNG_MASK)
255
return 0;
256
257
/* Number of 512 bit blocks of raw Noise Source output data that must
258
* be processed by either the Conditioning Function or the
259
* SP 800-90 DRBG ‘BC_DF’ functionality to yield a ‘full entropy’
260
* output value.
261
*/
262
val = 0x5 << RNG_CONFIG_MIN_REFIL_CYCLES_SHIFT;
263
264
/* Number of FRO samples that are XOR-ed together into one bit to be
265
* shifted into the main shift register
266
*/
267
val |= RNG_CONFIG_MAX_REFIL_CYCLES << RNG_CONFIG_MAX_REFIL_CYCLES_SHIFT;
268
omap_rng_write(priv, RNG_CONFIG_REG, val);
269
270
/* Enable all available FROs */
271
omap_rng_write(priv, RNG_FRODETUNE_REG, 0x0);
272
omap_rng_write(priv, RNG_FROENABLE_REG, RNG_REG_FROENABLE_MASK);
273
274
/* Enable TRNG */
275
val = RNG_CONTROL_ENABLE_TRNG_MASK;
276
omap_rng_write(priv, RNG_CONTROL_REG, val);
277
278
return 0;
279
}
280
281
static int omap4_rng_init(struct omap_rng_dev *priv)
282
{
283
u32 val;
284
285
/* Return if RNG is already running. */
286
if (omap_rng_read(priv, RNG_CONTROL_REG) & RNG_CONTROL_ENABLE_TRNG_MASK)
287
return 0;
288
289
val = RNG_CONFIG_MIN_REFIL_CYCLES << RNG_CONFIG_MIN_REFIL_CYCLES_SHIFT;
290
val |= RNG_CONFIG_MAX_REFIL_CYCLES << RNG_CONFIG_MAX_REFIL_CYCLES_SHIFT;
291
omap_rng_write(priv, RNG_CONFIG_REG, val);
292
293
omap_rng_write(priv, RNG_FRODETUNE_REG, 0x0);
294
omap_rng_write(priv, RNG_FROENABLE_REG, RNG_REG_FROENABLE_MASK);
295
val = RNG_ALARM_THRESHOLD << RNG_ALARMCNT_ALARM_TH_SHIFT;
296
val |= RNG_SHUTDOWN_THRESHOLD << RNG_ALARMCNT_SHUTDOWN_TH_SHIFT;
297
omap_rng_write(priv, RNG_ALARMCNT_REG, val);
298
299
val = RNG_CONTROL_STARTUP_CYCLES << RNG_CONTROL_STARTUP_CYCLES_SHIFT;
300
val |= RNG_CONTROL_ENABLE_TRNG_MASK;
301
omap_rng_write(priv, RNG_CONTROL_REG, val);
302
303
return 0;
304
}
305
306
static void omap4_rng_cleanup(struct omap_rng_dev *priv)
307
{
308
int val;
309
310
val = omap_rng_read(priv, RNG_CONTROL_REG);
311
val &= ~RNG_CONTROL_ENABLE_TRNG_MASK;
312
omap_rng_write(priv, RNG_CONTROL_REG, val);
313
}
314
315
static irqreturn_t omap4_rng_irq(int irq, void *dev_id)
316
{
317
struct omap_rng_dev *priv = dev_id;
318
u32 fro_detune, fro_enable;
319
320
/*
321
* Interrupt raised by a fro shutdown threshold, do the following:
322
* 1. Clear the alarm events.
323
* 2. De tune the FROs which are shutdown.
324
* 3. Re enable the shutdown FROs.
325
*/
326
omap_rng_write(priv, RNG_ALARMMASK_REG, 0x0);
327
omap_rng_write(priv, RNG_ALARMSTOP_REG, 0x0);
328
329
fro_enable = omap_rng_read(priv, RNG_FROENABLE_REG);
330
fro_detune = ~fro_enable & RNG_REG_FRODETUNE_MASK;
331
fro_detune = fro_detune | omap_rng_read(priv, RNG_FRODETUNE_REG);
332
fro_enable = RNG_REG_FROENABLE_MASK;
333
334
omap_rng_write(priv, RNG_FRODETUNE_REG, fro_detune);
335
omap_rng_write(priv, RNG_FROENABLE_REG, fro_enable);
336
337
omap_rng_write(priv, RNG_INTACK_REG, RNG_REG_INTACK_SHUTDOWN_OFLO_MASK);
338
339
return IRQ_HANDLED;
340
}
341
342
static struct omap_rng_pdata omap4_rng_pdata = {
343
.regs = (u16 *)reg_map_omap4,
344
.data_size = OMAP4_RNG_OUTPUT_SIZE,
345
.data_present = omap4_rng_data_present,
346
.init = omap4_rng_init,
347
.cleanup = omap4_rng_cleanup,
348
};
349
350
static struct omap_rng_pdata eip76_rng_pdata = {
351
.regs = (u16 *)reg_map_eip76,
352
.data_size = EIP76_RNG_OUTPUT_SIZE,
353
.data_present = omap4_rng_data_present,
354
.init = eip76_rng_init,
355
.cleanup = omap4_rng_cleanup,
356
};
357
358
static const struct of_device_id omap_rng_of_match[] __maybe_unused = {
359
{
360
.compatible = "ti,omap2-rng",
361
.data = &omap2_rng_pdata,
362
},
363
{
364
.compatible = "ti,omap4-rng",
365
.data = &omap4_rng_pdata,
366
},
367
{
368
.compatible = "inside-secure,safexcel-eip76",
369
.data = &eip76_rng_pdata,
370
},
371
{},
372
};
373
MODULE_DEVICE_TABLE(of, omap_rng_of_match);
374
375
static int of_get_omap_rng_device_details(struct omap_rng_dev *priv,
376
struct platform_device *pdev)
377
{
378
struct device *dev = &pdev->dev;
379
int irq, err;
380
381
priv->pdata = of_device_get_match_data(dev);
382
if (!priv->pdata)
383
return -ENODEV;
384
385
386
if (of_device_is_compatible(dev->of_node, "ti,omap4-rng") ||
387
of_device_is_compatible(dev->of_node, "inside-secure,safexcel-eip76")) {
388
irq = platform_get_irq(pdev, 0);
389
if (irq < 0)
390
return irq;
391
392
err = devm_request_irq(dev, irq, omap4_rng_irq,
393
IRQF_TRIGGER_NONE, dev_name(dev), priv);
394
if (err) {
395
dev_err(dev, "unable to request irq %d, err = %d\n",
396
irq, err);
397
return err;
398
}
399
400
/*
401
* On OMAP4, enabling the shutdown_oflo interrupt is
402
* done in the interrupt mask register. There is no
403
* such register on EIP76, and it's enabled by the
404
* same bit in the control register
405
*/
406
if (priv->pdata->regs[RNG_INTMASK_REG])
407
omap_rng_write(priv, RNG_INTMASK_REG,
408
RNG_SHUTDOWN_OFLO_MASK);
409
else
410
omap_rng_write(priv, RNG_CONTROL_REG,
411
RNG_SHUTDOWN_OFLO_MASK);
412
}
413
return 0;
414
}
415
416
static int get_omap_rng_device_details(struct omap_rng_dev *omap_rng)
417
{
418
/* Only OMAP2/3 can be non-DT */
419
omap_rng->pdata = &omap2_rng_pdata;
420
return 0;
421
}
422
423
static int omap_rng_probe(struct platform_device *pdev)
424
{
425
struct omap_rng_dev *priv;
426
struct device *dev = &pdev->dev;
427
int ret;
428
429
priv = devm_kzalloc(dev, sizeof(struct omap_rng_dev), GFP_KERNEL);
430
if (!priv)
431
return -ENOMEM;
432
433
priv->rng.read = omap_rng_do_read;
434
priv->rng.init = omap_rng_init;
435
priv->rng.cleanup = omap_rng_cleanup;
436
priv->rng.quality = 900;
437
438
priv->rng.priv = (unsigned long)priv;
439
platform_set_drvdata(pdev, priv);
440
priv->dev = dev;
441
442
priv->base = devm_platform_ioremap_resource(pdev, 0);
443
if (IS_ERR(priv->base)) {
444
ret = PTR_ERR(priv->base);
445
goto err_ioremap;
446
}
447
448
priv->rng.name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL);
449
if (!priv->rng.name) {
450
ret = -ENOMEM;
451
goto err_ioremap;
452
}
453
454
pm_runtime_enable(&pdev->dev);
455
ret = pm_runtime_resume_and_get(&pdev->dev);
456
if (ret < 0) {
457
dev_err(&pdev->dev, "Failed to runtime_get device: %d\n", ret);
458
goto err_ioremap;
459
}
460
461
priv->clk = devm_clk_get(&pdev->dev, NULL);
462
if (PTR_ERR(priv->clk) == -EPROBE_DEFER)
463
return -EPROBE_DEFER;
464
if (!IS_ERR(priv->clk)) {
465
ret = clk_prepare_enable(priv->clk);
466
if (ret) {
467
dev_err(&pdev->dev,
468
"Unable to enable the clk: %d\n", ret);
469
goto err_register;
470
}
471
}
472
473
priv->clk_reg = devm_clk_get(&pdev->dev, "reg");
474
if (PTR_ERR(priv->clk_reg) == -EPROBE_DEFER)
475
return -EPROBE_DEFER;
476
if (!IS_ERR(priv->clk_reg)) {
477
ret = clk_prepare_enable(priv->clk_reg);
478
if (ret) {
479
dev_err(&pdev->dev,
480
"Unable to enable the register clk: %d\n",
481
ret);
482
goto err_register;
483
}
484
}
485
486
ret = (dev->of_node) ? of_get_omap_rng_device_details(priv, pdev) :
487
get_omap_rng_device_details(priv);
488
if (ret)
489
goto err_register;
490
491
ret = devm_hwrng_register(&pdev->dev, &priv->rng);
492
if (ret)
493
goto err_register;
494
495
dev_info(&pdev->dev, "Random Number Generator ver. %02x\n",
496
omap_rng_read(priv, RNG_REV_REG));
497
498
return 0;
499
500
err_register:
501
priv->base = NULL;
502
pm_runtime_put_sync(&pdev->dev);
503
pm_runtime_disable(&pdev->dev);
504
505
clk_disable_unprepare(priv->clk_reg);
506
clk_disable_unprepare(priv->clk);
507
err_ioremap:
508
dev_err(dev, "initialization failed.\n");
509
return ret;
510
}
511
512
static void omap_rng_remove(struct platform_device *pdev)
513
{
514
struct omap_rng_dev *priv = platform_get_drvdata(pdev);
515
516
517
priv->pdata->cleanup(priv);
518
519
pm_runtime_put_sync(&pdev->dev);
520
pm_runtime_disable(&pdev->dev);
521
522
clk_disable_unprepare(priv->clk);
523
clk_disable_unprepare(priv->clk_reg);
524
}
525
526
static int __maybe_unused omap_rng_suspend(struct device *dev)
527
{
528
struct omap_rng_dev *priv = dev_get_drvdata(dev);
529
530
priv->pdata->cleanup(priv);
531
pm_runtime_put_sync(dev);
532
533
return 0;
534
}
535
536
static int __maybe_unused omap_rng_resume(struct device *dev)
537
{
538
struct omap_rng_dev *priv = dev_get_drvdata(dev);
539
int ret;
540
541
ret = pm_runtime_resume_and_get(dev);
542
if (ret < 0) {
543
dev_err(dev, "Failed to runtime_get device: %d\n", ret);
544
return ret;
545
}
546
547
priv->pdata->init(priv);
548
549
return 0;
550
}
551
552
static SIMPLE_DEV_PM_OPS(omap_rng_pm, omap_rng_suspend, omap_rng_resume);
553
554
static struct platform_driver omap_rng_driver = {
555
.driver = {
556
.name = "omap_rng",
557
.pm = &omap_rng_pm,
558
.of_match_table = of_match_ptr(omap_rng_of_match),
559
},
560
.probe = omap_rng_probe,
561
.remove = omap_rng_remove,
562
};
563
564
module_platform_driver(omap_rng_driver);
565
MODULE_ALIAS("platform:omap_rng");
566
MODULE_AUTHOR("Deepak Saxena (and others)");
567
MODULE_DESCRIPTION("RNG driver for TI OMAP CPU family");
568
MODULE_LICENSE("GPL");
569
570