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