Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/arm/broadcom/bcm2835/bcm2835_rng.c
39566 views
1
/*
2
* Copyright (c) 2015, 2016, Stephen J. Kiernan
3
* All rights reserved.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
*
14
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
* SUCH DAMAGE.
25
*/
26
27
28
#include <sys/param.h>
29
#include <sys/kernel.h>
30
#include <sys/ktr.h>
31
#include <sys/lock.h>
32
#include <sys/malloc.h>
33
#include <sys/module.h>
34
#include <sys/random.h>
35
#include <sys/sbuf.h>
36
#include <sys/sysctl.h>
37
#include <sys/selinfo.h>
38
#include <sys/systm.h>
39
#include <sys/bus.h>
40
#include <sys/rman.h>
41
42
#include <machine/bus.h>
43
#include <machine/resource.h>
44
45
#include <dev/ofw/openfirm.h>
46
#include <dev/ofw/ofw_bus.h>
47
#include <dev/ofw/ofw_bus_subr.h>
48
49
#include <dev/random/randomdev.h>
50
#include <dev/random/random_harvestq.h>
51
52
static device_attach_t bcm2835_rng_attach;
53
static device_detach_t bcm2835_rng_detach;
54
static device_probe_t bcm2835_rng_probe;
55
56
#define RNG_CTRL 0x00 /* RNG Control Register */
57
#define RNG_COMBLK1_OSC 0x003f0000 /* Combiner Blk 1 Oscillator */
58
#define RNG_COMBLK1_OSC_SHIFT 16
59
#define RNG_COMBLK2_OSC 0x0fc00000 /* Combiner Blk 2 Oscillator */
60
#define RNG_COMBLK2_OSC_SHIFT 22
61
#define RNG_JCLK_BYP_DIV_CNT 0x0000ff00 /* Jitter clk bypass divider
62
count */
63
#define RNG_JCLK_BYP_DIV_CNT_SHIFT 8
64
#define RNG_JCLK_BYP_SRC 0x00000020 /* Jitter clk bypass source */
65
#define RNG_JCLK_BYP_SEL 0x00000010 /* Jitter clk bypass select */
66
#define RNG_RBG2X 0x00000002 /* RBG 2X SPEED */
67
#define RNG_RBGEN_BIT 0x00000001 /* Enable RNG bit */
68
69
#define BCM2835_RNG_STATUS 0x04 /* BCM2835 RNG status register */
70
#define BCM2838_RNG_STATUS 0x18 /* BCM2838 RNG status register */
71
72
#define BCM2838_RNG_COUNT 0x24 /* How many values available */
73
#define BCM2838_COUNT_VAL_MASK 0x000000ff
74
75
#define BCM2835_RND_VAL_SHIFT 24 /* Shift for valid words */
76
#define BCM2835_RND_VAL_MASK 0x000000ff /* Number valid words mask */
77
#define BCM2835_RND_VAL_WARM_CNT 0x40000 /* RNG Warm Up count */
78
#define BCM2835_RND_WARM_CNT 0xfffff /* RNG Warm Up Count mask */
79
80
#define BCM2835_RNG_DATA 0x08 /* RNG Data Register */
81
#define BCM2838_RNG_DATA 0x20
82
#define RNG_FF_THRES 0x0c
83
#define RNG_FF_THRES_MASK 0x0000001f
84
85
#define BCM2835_RNG_INT_MASK 0x10
86
#define BCM2835_RNG_INT_OFF_BIT 0x00000001
87
88
#define RNG_FF_DEFAULT 0x10 /* FIFO threshold default */
89
#define RNG_FIFO_WORDS (RNG_FF_DEFAULT / sizeof(uint32_t))
90
91
#define RNG_NUM_OSCILLATORS 6
92
#define RNG_STALL_COUNT_DEFAULT 10
93
94
#define RNG_CALLOUT_TICKS (hz * 4)
95
96
struct bcm_rng_conf {
97
bus_size_t control_reg;
98
bus_size_t status_reg;
99
bus_size_t count_reg;
100
bus_size_t data_reg;
101
bus_size_t intr_mask_reg;
102
uint32_t intr_disable_bit;
103
uint32_t count_value_shift;
104
uint32_t count_value_mask;
105
uint32_t warmup_count;
106
bool allow_2x_mode;
107
bool can_diagnose;
108
/* XXX diag regs */
109
};
110
111
static const struct bcm_rng_conf bcm2835_rng_conf = {
112
.control_reg = RNG_CTRL,
113
.status_reg = BCM2835_RNG_STATUS,
114
.count_reg = BCM2835_RNG_STATUS, /* Same register */
115
.data_reg = BCM2835_RNG_DATA,
116
.intr_mask_reg = BCM2835_RNG_INT_MASK,
117
.intr_disable_bit = BCM2835_RNG_INT_OFF_BIT,
118
.count_value_shift = BCM2835_RND_VAL_SHIFT,
119
.count_value_mask = BCM2835_RND_VAL_MASK,
120
.warmup_count = BCM2835_RND_VAL_WARM_CNT,
121
.allow_2x_mode = true,
122
.can_diagnose = true
123
};
124
125
static const struct bcm_rng_conf bcm2838_rng_conf = {
126
.control_reg = RNG_CTRL,
127
.status_reg = BCM2838_RNG_STATUS,
128
.count_reg = BCM2838_RNG_COUNT,
129
.data_reg = BCM2838_RNG_DATA,
130
.intr_mask_reg = 0,
131
.intr_disable_bit = 0,
132
.count_value_shift = 0,
133
.count_value_mask = BCM2838_COUNT_VAL_MASK,
134
.warmup_count = 0,
135
.allow_2x_mode = false,
136
.can_diagnose = false
137
};
138
139
struct bcm2835_rng_softc {
140
device_t sc_dev;
141
struct resource * sc_mem_res;
142
struct resource * sc_irq_res;
143
void * sc_intr_hdl;
144
struct bcm_rng_conf const* conf;
145
uint32_t sc_buf[RNG_FIFO_WORDS];
146
struct callout sc_rngto;
147
int sc_stall_count;
148
int sc_rbg2x;
149
long sc_underrun;
150
};
151
152
static struct ofw_compat_data compat_data[] = {
153
{"broadcom,bcm2835-rng", (uintptr_t)&bcm2835_rng_conf},
154
{"brcm,bcm2835-rng", (uintptr_t)&bcm2835_rng_conf},
155
156
{"brcm,bcm2711-rng200", (uintptr_t)&bcm2838_rng_conf},
157
{"brcm,bcm2838-rng", (uintptr_t)&bcm2838_rng_conf},
158
{"brcm,bcm2838-rng200", (uintptr_t)&bcm2838_rng_conf},
159
{"brcm,bcm7211-rng", (uintptr_t)&bcm2838_rng_conf},
160
{"brcm,bcm7278-rng", (uintptr_t)&bcm2838_rng_conf},
161
{"brcm,iproc-rng200", (uintptr_t)&bcm2838_rng_conf},
162
{NULL, 0}
163
};
164
165
static __inline void
166
bcm2835_rng_stat_inc_underrun(struct bcm2835_rng_softc *sc)
167
{
168
169
atomic_add_long(&sc->sc_underrun, 1);
170
}
171
172
static __inline uint32_t
173
bcm2835_rng_read4(struct bcm2835_rng_softc *sc, bus_size_t off)
174
{
175
176
return bus_read_4(sc->sc_mem_res, off);
177
}
178
179
static __inline void
180
bcm2835_rng_read_multi4(struct bcm2835_rng_softc *sc, bus_size_t off,
181
uint32_t *datap, bus_size_t count)
182
{
183
184
bus_read_multi_4(sc->sc_mem_res, off, datap, count);
185
}
186
187
static __inline void
188
bcm2835_rng_write4(struct bcm2835_rng_softc *sc, bus_size_t off, uint32_t val)
189
{
190
191
bus_write_4(sc->sc_mem_res, off, val);
192
}
193
194
static void
195
bcm2835_rng_dump_registers(struct bcm2835_rng_softc *sc, struct sbuf *sbp)
196
{
197
uint32_t comblk2_osc, comblk1_osc, jclk_byp_div, val;
198
int i;
199
200
if (!sc->conf->can_diagnose)
201
/* Not implemented. */
202
return;
203
204
/* Display RNG control register contents */
205
val = bcm2835_rng_read4(sc, sc->conf->control_reg);
206
sbuf_printf(sbp, "RNG_CTRL (%08x)\n", val);
207
208
comblk2_osc = (val & RNG_COMBLK2_OSC) >> RNG_COMBLK2_OSC_SHIFT;
209
sbuf_printf(sbp, " RNG_COMBLK2_OSC (%02x)\n", comblk2_osc);
210
for (i = 0; i < RNG_NUM_OSCILLATORS; i++)
211
if ((comblk2_osc & (1 << i)) == 0)
212
sbuf_printf(sbp, " Oscillator %d enabled\n", i + 1);
213
214
comblk1_osc = (val & RNG_COMBLK1_OSC) >> RNG_COMBLK1_OSC_SHIFT;
215
sbuf_printf(sbp, " RNG_COMBLK1_OSC (%02x)\n", comblk1_osc);
216
for (i = 0; i < RNG_NUM_OSCILLATORS; i++)
217
if ((comblk1_osc & (1 << i)) == 0)
218
sbuf_printf(sbp, " Oscillator %d enabled\n", i + 1);
219
220
jclk_byp_div = (val & RNG_JCLK_BYP_DIV_CNT) >>
221
RNG_JCLK_BYP_DIV_CNT_SHIFT;
222
sbuf_printf(sbp,
223
" RNG_JCLK_BYP_DIV_CNT (%02x)\n APB clock frequency / %d\n",
224
jclk_byp_div, 2 * (jclk_byp_div + 1));
225
226
sbuf_printf(sbp, " RNG_JCLK_BYP_SRC:\n %s\n",
227
(val & RNG_JCLK_BYP_SRC) ? "Use divided down APB clock" :
228
"Use RNG clock (APB clock)");
229
230
sbuf_printf(sbp, " RNG_JCLK_BYP_SEL:\n %s\n",
231
(val & RNG_JCLK_BYP_SEL) ? "Bypass internal jitter clock" :
232
"Use internal jitter clock");
233
234
if ((val & RNG_RBG2X) != 0)
235
sbuf_cat(sbp, " RNG_RBG2X: RNG 2X SPEED enabled\n");
236
237
if ((val & RNG_RBGEN_BIT) != 0)
238
sbuf_cat(sbp, " RNG_RBGEN_BIT: RBG enabled\n");
239
240
/* Display RNG status register contents */
241
val = bcm2835_rng_read4(sc, sc->conf->status_reg);
242
sbuf_printf(sbp, "RNG_CTRL (%08x)\n", val);
243
sbuf_printf(sbp, " RND_VAL: %02x\n",
244
(val >> sc->conf->count_value_shift) & sc->conf->count_value_mask);
245
sbuf_printf(sbp, " RND_WARM_CNT: %05x\n", val & sc->conf->warmup_count);
246
247
/* Display FIFO threshold register contents */
248
val = bcm2835_rng_read4(sc, RNG_FF_THRES);
249
sbuf_printf(sbp, "RNG_FF_THRES: %05x\n", val & RNG_FF_THRES_MASK);
250
251
/* Display interrupt mask register contents */
252
val = bcm2835_rng_read4(sc, sc->conf->intr_mask_reg);
253
sbuf_printf(sbp, "RNG_INT_MASK: interrupt %s\n",
254
((val & sc->conf->intr_disable_bit) != 0) ? "disabled" : "enabled");
255
}
256
257
static void
258
bcm2835_rng_disable_intr(struct bcm2835_rng_softc *sc)
259
{
260
uint32_t mask;
261
262
/* Set the interrupt off bit in the interrupt mask register */
263
mask = bcm2835_rng_read4(sc, sc->conf->intr_mask_reg);
264
mask |= sc->conf->intr_disable_bit;
265
bcm2835_rng_write4(sc, sc->conf->intr_mask_reg, mask);
266
}
267
268
static void
269
bcm2835_rng_start(struct bcm2835_rng_softc *sc)
270
{
271
uint32_t ctrl;
272
273
/* Disable the interrupt */
274
if (sc->conf->intr_mask_reg)
275
bcm2835_rng_disable_intr(sc);
276
277
/* Set the warmup count */
278
if (sc->conf->warmup_count > 0)
279
bcm2835_rng_write4(sc, sc->conf->status_reg,
280
sc->conf->warmup_count);
281
282
/* Enable the RNG */
283
ctrl = bcm2835_rng_read4(sc, sc->conf->control_reg);
284
ctrl |= RNG_RBGEN_BIT;
285
if (sc->sc_rbg2x && sc->conf->allow_2x_mode)
286
ctrl |= RNG_RBG2X;
287
bcm2835_rng_write4(sc, sc->conf->control_reg, ctrl);
288
}
289
290
static void
291
bcm2835_rng_stop(struct bcm2835_rng_softc *sc)
292
{
293
uint32_t ctrl;
294
295
/* Disable the RNG */
296
ctrl = bcm2835_rng_read4(sc, sc->conf->control_reg);
297
ctrl &= ~RNG_RBGEN_BIT;
298
bcm2835_rng_write4(sc, sc->conf->control_reg, ctrl);
299
}
300
301
static void
302
bcm2835_rng_enqueue_harvest(struct bcm2835_rng_softc *sc, uint32_t nread)
303
{
304
char *sc_buf_chunk;
305
uint32_t chunk_size;
306
uint32_t cnt;
307
308
chunk_size = sizeof(((struct harvest_event *)0)->he_entropy);
309
cnt = nread * sizeof(uint32_t);
310
sc_buf_chunk = (void*)sc->sc_buf;
311
312
while (cnt > 0) {
313
uint32_t size;
314
315
size = MIN(cnt, chunk_size);
316
317
random_harvest_queue(sc_buf_chunk, size, RANDOM_PURE_BROADCOM);
318
319
sc_buf_chunk += size;
320
cnt -= size;
321
}
322
}
323
324
static void
325
bcm2835_rng_harvest(void *arg)
326
{
327
uint32_t *dest;
328
uint32_t hwcount;
329
u_int cnt, nread, num_avail, num_words;
330
int seen_underrun, num_stalls;
331
struct bcm2835_rng_softc *sc = arg;
332
333
dest = sc->sc_buf;
334
nread = num_words = 0;
335
seen_underrun = num_stalls = 0;
336
337
for (cnt = sizeof(sc->sc_buf) / sizeof(uint32_t); cnt > 0;
338
cnt -= num_words) {
339
/* Read count register to find out how many words available */
340
hwcount = bcm2835_rng_read4(sc, sc->conf->count_reg);
341
num_avail = (hwcount >> sc->conf->count_value_shift) &
342
sc->conf->count_value_mask;
343
344
/* If we have none... */
345
if (num_avail == 0) {
346
bcm2835_rng_stat_inc_underrun(sc);
347
if (++seen_underrun >= sc->sc_stall_count) {
348
if (num_stalls++ > 0) {
349
device_printf(sc->sc_dev,
350
"RNG stalled, disabling device\n");
351
bcm2835_rng_stop(sc);
352
break;
353
} else {
354
device_printf(sc->sc_dev,
355
"Too many underruns, resetting\n");
356
bcm2835_rng_stop(sc);
357
bcm2835_rng_start(sc);
358
seen_underrun = 0;
359
}
360
}
361
/* Try again */
362
continue;
363
}
364
365
CTR2(KTR_DEV, "%s: %d words available in RNG FIFO",
366
device_get_nameunit(sc->sc_dev), num_avail);
367
368
/* Pull MIN(num_avail, cnt) words from the FIFO */
369
num_words = (num_avail > cnt) ? cnt : num_avail;
370
bcm2835_rng_read_multi4(sc, sc->conf->data_reg, dest,
371
num_words);
372
dest += num_words;
373
nread += num_words;
374
}
375
376
bcm2835_rng_enqueue_harvest(sc, nread);
377
378
callout_reset(&sc->sc_rngto, RNG_CALLOUT_TICKS, bcm2835_rng_harvest, sc);
379
}
380
381
static int
382
sysctl_bcm2835_rng_2xspeed(SYSCTL_HANDLER_ARGS)
383
{
384
struct bcm2835_rng_softc *sc = arg1;
385
int error, rbg2x;
386
387
rbg2x = sc->sc_rbg2x;
388
error = sysctl_handle_int(oidp, &rbg2x, 0, req);
389
if (error)
390
return (error);
391
if (req->newptr == NULL)
392
return (error);
393
if (rbg2x == sc->sc_rbg2x)
394
return (0);
395
396
/* Reset the RNG */
397
bcm2835_rng_stop(sc);
398
sc->sc_rbg2x = rbg2x;
399
bcm2835_rng_start(sc);
400
401
return (0);
402
}
403
404
#ifdef BCM2835_RNG_DEBUG_REGISTERS
405
static int
406
sysctl_bcm2835_rng_dump(SYSCTL_HANDLER_ARGS)
407
{
408
struct sbuf sb;
409
struct bcm2835_rng_softc *sc = arg1;
410
int error;
411
412
error = sysctl_wire_old_buffer(req, 0);
413
if (error != 0)
414
return (error);
415
sbuf_new_for_sysctl(&sb, NULL, 128, req);
416
bcm2835_rng_dump_registers(sc, &sb);
417
error = sbuf_finish(&sb);
418
sbuf_delete(&sb);
419
return (error);
420
}
421
#endif
422
423
static int
424
bcm2835_rng_probe(device_t dev)
425
{
426
427
if (!ofw_bus_status_okay(dev))
428
return (ENXIO);
429
430
if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
431
return (ENXIO);
432
433
device_set_desc(dev, "Broadcom BCM2835/BCM2838 RNG");
434
435
return (BUS_PROBE_DEFAULT);
436
}
437
438
static int
439
bcm2835_rng_attach(device_t dev)
440
{
441
struct bcm2835_rng_softc *sc;
442
struct sysctl_ctx_list *sysctl_ctx;
443
struct sysctl_oid *sysctl_tree;
444
int error, rid;
445
446
error = 0;
447
sc = device_get_softc(dev);
448
sc->sc_dev = dev;
449
450
sc->conf = (void const*)ofw_bus_search_compatible(dev, compat_data)->ocd_data;
451
KASSERT(sc->conf != NULL, ("bcm2835_rng_attach: sc->conf == NULL"));
452
453
sc->sc_stall_count = RNG_STALL_COUNT_DEFAULT;
454
455
/* Initialize callout */
456
callout_init(&sc->sc_rngto, CALLOUT_MPSAFE);
457
458
TUNABLE_INT_FETCH("bcmrng.stall_count", &sc->sc_stall_count);
459
if (sc->conf->allow_2x_mode)
460
TUNABLE_INT_FETCH("bcmrng.2xspeed", &sc->sc_rbg2x);
461
462
/* Allocate memory resources */
463
rid = 0;
464
sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
465
RF_ACTIVE);
466
if (sc->sc_mem_res == NULL) {
467
bcm2835_rng_detach(dev);
468
return (ENXIO);
469
}
470
471
/* Start the RNG */
472
bcm2835_rng_start(sc);
473
474
/* Dump the registers if booting verbose */
475
if (bootverbose) {
476
struct sbuf sb;
477
478
(void) sbuf_new(&sb, NULL, 256,
479
SBUF_AUTOEXTEND | SBUF_INCLUDENUL);
480
bcm2835_rng_dump_registers(sc, &sb);
481
sbuf_trim(&sb);
482
error = sbuf_finish(&sb);
483
if (error == 0)
484
device_printf(dev, "%s", sbuf_data(&sb));
485
sbuf_delete(&sb);
486
}
487
488
sysctl_ctx = device_get_sysctl_ctx(dev);
489
sysctl_tree = device_get_sysctl_tree(dev);
490
SYSCTL_ADD_LONG(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
491
"underrun", CTLFLAG_RD, &sc->sc_underrun,
492
"Number of FIFO underruns");
493
if (sc->conf->allow_2x_mode)
494
SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
495
"2xspeed", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, sc, 0,
496
sysctl_bcm2835_rng_2xspeed, "I", "Enable RBG 2X SPEED");
497
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
498
"stall_count", CTLFLAG_RW, &sc->sc_stall_count,
499
RNG_STALL_COUNT_DEFAULT, "Number of underruns to assume RNG stall");
500
#ifdef BCM2835_RNG_DEBUG_REGISTERS
501
SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
502
"dumpregs", CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, 0,
503
sysctl_bcm2835_rng_dump, "S", "Dump RNG registers");
504
#endif
505
506
/*
507
* Schedule the initial harvesting one second from now, which should give the
508
* hardware RNG plenty of time to generate the first random bytes.
509
*/
510
callout_reset(&sc->sc_rngto, hz, bcm2835_rng_harvest, sc);
511
512
return (0);
513
}
514
515
static int
516
bcm2835_rng_detach(device_t dev)
517
{
518
struct bcm2835_rng_softc *sc;
519
520
sc = device_get_softc(dev);
521
522
/* Stop the RNG */
523
bcm2835_rng_stop(sc);
524
525
/* Drain the callout it */
526
callout_drain(&sc->sc_rngto);
527
528
/* Release memory resource */
529
if (sc->sc_mem_res != NULL)
530
bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
531
532
return (0);
533
}
534
535
static device_method_t bcm2835_rng_methods[] = {
536
/* Device interface */
537
DEVMETHOD(device_probe, bcm2835_rng_probe),
538
DEVMETHOD(device_attach, bcm2835_rng_attach),
539
DEVMETHOD(device_detach, bcm2835_rng_detach),
540
541
DEVMETHOD_END
542
};
543
544
static driver_t bcm2835_rng_driver = {
545
"bcmrng",
546
bcm2835_rng_methods,
547
sizeof(struct bcm2835_rng_softc)
548
};
549
550
DRIVER_MODULE(bcm2835_rng, simplebus, bcm2835_rng_driver, 0, 0);
551
DRIVER_MODULE(bcm2835_rng, ofwbus, bcm2835_rng_driver, 0, 0);
552
MODULE_VERSION(bcm2835_rng, 1);
553
MODULE_DEPEND(bcm2835_rng, randomdev, 1, 1, 1);
554
555