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
bcm2835_rng_stat_inc_underrun(struct bcm2835_rng_softc * sc)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
bcm2835_rng_read4(struct bcm2835_rng_softc * sc,bus_size_t off)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
bcm2835_rng_read_multi4(struct bcm2835_rng_softc * sc,bus_size_t off,uint32_t * datap,bus_size_t count)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
bcm2835_rng_write4(struct bcm2835_rng_softc * sc,bus_size_t off,uint32_t val)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
bcm2835_rng_dump_registers(struct bcm2835_rng_softc * sc,struct sbuf * sbp)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
bcm2835_rng_disable_intr(struct bcm2835_rng_softc * sc)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
bcm2835_rng_start(struct bcm2835_rng_softc * sc)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
bcm2835_rng_stop(struct bcm2835_rng_softc * sc)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
bcm2835_rng_enqueue_harvest(struct bcm2835_rng_softc * sc,uint32_t nread)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
bcm2835_rng_harvest(void * arg)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
sysctl_bcm2835_rng_2xspeed(SYSCTL_HANDLER_ARGS)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
sysctl_bcm2835_rng_dump(SYSCTL_HANDLER_ARGS)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
bcm2835_rng_probe(device_t dev)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
bcm2835_rng_attach(device_t dev)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
bcm2835_rng_detach(device_t dev)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