2 * Copyright (c) 2015, 2016, Stephen J. Kiernan
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
27 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
31 #include <sys/param.h>
32 #include <sys/kernel.h>
34 #include <sys/malloc.h>
35 #include <sys/module.h>
36 #include <sys/random.h>
38 #include <sys/sysctl.h>
39 #include <sys/selinfo.h>
40 #include <sys/systm.h>
44 #include <machine/bus.h>
45 #include <machine/resource.h>
47 #include <dev/ofw/openfirm.h>
48 #include <dev/ofw/ofw_bus.h>
49 #include <dev/ofw/ofw_bus_subr.h>
51 #include <dev/random/randomdev.h>
52 #include <dev/random/random_harvestq.h>
54 #if !defined(BCM2835_RNG_USE_CALLOUT)
55 #define BCM2835_RNG_USE_INTERRUPT
58 static device_attach_t bcm2835_rng_attach;
59 static device_detach_t bcm2835_rng_detach;
60 static device_probe_t bcm2835_rng_probe;
62 #define RNG_CTRL 0x00 /* RNG Control Register */
63 #define RNG_COMBLK1_OSC 0x003f0000 /* Combiner Blk 1 Oscillator */
64 #define RNG_COMBLK1_OSC_SHIFT 16
65 #define RNG_COMBLK2_OSC 0x0fc00000 /* Combiner Blk 2 Oscillator */
66 #define RNG_COMBLK2_OSC_SHIFT 22
67 #define RNG_JCLK_BYP_DIV_CNT 0x0000ff00 /* Jitter clk bypass divider
69 #define RNG_JCLK_BYP_DIV_CNT_SHIFT 8
70 #define RNG_JCLK_BYP_SRC 0x00000020 /* Jitter clk bypass source */
71 #define RNG_JCLK_BYP_SEL 0x00000010 /* Jitter clk bypass select */
72 #define RNG_RBG2X 0x00000002 /* RBG 2X SPEED */
73 #define RNG_RBGEN_BIT 0x00000001 /* Enable RNG bit */
75 #define RNG_STATUS 0x04 /* RNG status register */
76 #define RND_VAL_SHIFT 24 /* Shift for valid words */
77 #define RND_VAL_MASK 0x000000ff /* Number valid words mask */
78 #define RND_VAL_WARM_CNT 0x40000 /* RNG Warm Up count */
79 #define RND_WARM_CNT 0xfffff /* RNG Warm Up Count mask */
81 #define RNG_DATA 0x08 /* RNG Data Register */
82 #define RNG_FF_THRES 0x0c
83 #define RNG_FF_THRES_MASK 0x0000001f
85 #define RNG_INT_MASK 0x10
86 #define RNG_INT_OFF_BIT 0x00000001
88 #define RNG_FF_DEFAULT 0x10 /* FIFO threshold default */
90 #define RNG_FIFO_WORDS (RNG_FF_DEFAULT / sizeof(uint32_t))
92 #define RNG_NUM_OSCILLATORS 6
93 #define RNG_STALL_COUNT_DEFAULT 10
95 struct bcm2835_rng_softc {
97 struct resource * sc_mem_res;
98 struct resource * sc_irq_res;
100 #if defined(BCM2835_RNG_USE_CALLOUT) || defined(BCM2835_RNG_USE_INTERRUPT)
101 uint32_t sc_buf[RNG_FIFO_WORDS];
103 #if defined(BCM2835_RNG_USE_CALLOUT)
104 struct callout sc_rngto;
112 static struct ofw_compat_data compat_data[] = {
113 {"broadcom,bcm2835-rng", 1},
114 {"brcm,bcm2835-rng", 1},
119 bcm2835_rng_stat_inc_underrun(struct bcm2835_rng_softc *sc)
122 atomic_add_long(&sc->sc_underrun, 1);
125 static __inline uint32_t
126 bcm2835_rng_read4(struct bcm2835_rng_softc *sc, bus_size_t off)
129 return bus_read_4(sc->sc_mem_res, off);
133 bcm2835_rng_read_multi4(struct bcm2835_rng_softc *sc, bus_size_t off,
134 uint32_t *datap, bus_size_t count)
137 bus_read_multi_4(sc->sc_mem_res, off, datap, count);
141 bcm2835_rng_write4(struct bcm2835_rng_softc *sc, bus_size_t off, uint32_t val)
144 bus_write_4(sc->sc_mem_res, off, val);
148 bcm2835_rng_dump_registers(struct bcm2835_rng_softc *sc, struct sbuf *sbp)
150 uint32_t comblk2_osc, comblk1_osc, jclk_byp_div, val;
153 /* Display RNG control register contents */
154 val = bcm2835_rng_read4(sc, RNG_CTRL);
155 sbuf_printf(sbp, "RNG_CTRL (%08x)\n", val);
157 comblk2_osc = (val & RNG_COMBLK2_OSC) >> RNG_COMBLK2_OSC_SHIFT;
158 sbuf_printf(sbp, " RNG_COMBLK2_OSC (%02x)\n", comblk2_osc);
159 for (i = 0; i < RNG_NUM_OSCILLATORS; i++)
160 if ((comblk2_osc & (1 << i)) == 0)
161 sbuf_printf(sbp, " Oscillator %d enabled\n", i + 1);
163 comblk1_osc = (val & RNG_COMBLK1_OSC) >> RNG_COMBLK1_OSC_SHIFT;
164 sbuf_printf(sbp, " RNG_COMBLK1_OSC (%02x)\n", comblk1_osc);
165 for (i = 0; i < RNG_NUM_OSCILLATORS; i++)
166 if ((comblk1_osc & (1 << i)) == 0)
167 sbuf_printf(sbp, " Oscillator %d enabled\n", i + 1);
169 jclk_byp_div = (val & RNG_JCLK_BYP_DIV_CNT) >>
170 RNG_JCLK_BYP_DIV_CNT_SHIFT;
172 " RNG_JCLK_BYP_DIV_CNT (%02x)\n APB clock frequency / %d\n",
173 jclk_byp_div, 2 * (jclk_byp_div + 1));
175 sbuf_printf(sbp, " RNG_JCLK_BYP_SRC:\n %s\n",
176 (val & RNG_JCLK_BYP_SRC) ? "Use divided down APB clock" :
177 "Use RNG clock (APB clock)");
179 sbuf_printf(sbp, " RNG_JCLK_BYP_SEL:\n %s\n",
180 (val & RNG_JCLK_BYP_SEL) ? "Bypass internal jitter clock" :
181 "Use internal jitter clock");
183 if ((val & RNG_RBG2X) != 0)
184 sbuf_cat(sbp, " RNG_RBG2X: RNG 2X SPEED enabled\n");
186 if ((val & RNG_RBGEN_BIT) != 0)
187 sbuf_cat(sbp, " RNG_RBGEN_BIT: RBG enabled\n");
189 /* Display RNG status register contents */
190 val = bcm2835_rng_read4(sc, RNG_STATUS);
191 sbuf_printf(sbp, "RNG_CTRL (%08x)\n", val);
192 sbuf_printf(sbp, " RND_VAL: %02x\n",
193 (val >> RND_VAL_SHIFT) & RND_VAL_MASK);
194 sbuf_printf(sbp, " RND_WARM_CNT: %05x\n", val & RND_WARM_CNT);
196 /* Display FIFO threshold register contents */
197 val = bcm2835_rng_read4(sc, RNG_FF_THRES);
198 sbuf_printf(sbp, "RNG_FF_THRES: %05x\n", val & RNG_FF_THRES_MASK);
200 /* Display interrupt mask register contents */
201 val = bcm2835_rng_read4(sc, RNG_INT_MASK);
202 sbuf_printf(sbp, "RNG_INT_MASK: interrupt %s\n",
203 ((val & RNG_INT_OFF_BIT) != 0) ? "disabled" : "enabled");
207 bcm2835_rng_disable_intr(struct bcm2835_rng_softc *sc)
211 /* Set the interrupt off bit in the interrupt mask register */
212 mask = bcm2835_rng_read4(sc, RNG_INT_MASK);
213 mask |= RNG_INT_OFF_BIT;
214 bcm2835_rng_write4(sc, RNG_INT_MASK, mask);
217 #if defined(BCM2835_RNG_USE_INTERRUPT)
219 bcm2835_rng_enable_intr(struct bcm2835_rng_softc *sc)
223 /* Clear the interrupt off bit in the interrupt mask register */
224 mask = bcm2835_rng_read4(sc, RNG_INT_MASK);
225 mask &= ~RNG_INT_OFF_BIT;
226 bcm2835_rng_write4(sc, RNG_INT_MASK, mask);
231 bcm2835_rng_start(struct bcm2835_rng_softc *sc)
235 /* Disable the interrupt */
236 bcm2835_rng_disable_intr(sc);
238 /* Set the warmup count */
239 bcm2835_rng_write4(sc, RNG_STATUS, RND_VAL_WARM_CNT);
242 ctrl = bcm2835_rng_read4(sc, RNG_CTRL);
243 ctrl |= RNG_RBGEN_BIT;
246 bcm2835_rng_write4(sc, RNG_CTRL, ctrl);
248 #if defined(BCM2835_RNG_USE_INTERRUPT)
249 /* Enable the interrupt */
250 bcm2835_rng_enable_intr(sc);
255 bcm2835_rng_stop(struct bcm2835_rng_softc *sc)
259 /* Disable the RNG */
260 ctrl = bcm2835_rng_read4(sc, RNG_CTRL);
261 ctrl &= ~RNG_RBGEN_BIT;
262 bcm2835_rng_write4(sc, RNG_CTRL, ctrl);
266 bcm2835_rng_harvest(struct bcm2835_rng_softc *sc)
270 u_int cnt, nread, num_avail, num_words;
271 int seen_underrun, num_stalls;
274 nread = num_words = 0;
275 seen_underrun = num_stalls = 0;
276 for (cnt = sizeof(sc->sc_buf) / sizeof(uint32_t); cnt > 0;
278 /* Read status register to find out how many words available */
279 status = bcm2835_rng_read4(sc, RNG_STATUS);
280 num_avail = (status >> RND_VAL_SHIFT) & RND_VAL_MASK;
282 /* If we have none... */
283 if (num_avail == 0) {
284 bcm2835_rng_stat_inc_underrun(sc);
285 if (++seen_underrun >= sc->sc_stall_count) {
286 if (num_stalls++ > 0) {
287 device_printf(sc->sc_dev,
288 "RNG stalled, disabling device\n");
289 bcm2835_rng_stop(sc);
292 device_printf(sc->sc_dev,
293 "Too many underruns, resetting\n");
294 bcm2835_rng_stop(sc);
295 bcm2835_rng_start(sc);
303 CTR2(KTR_DEV, "%s: %d words available in RNG FIFO",
304 device_get_nameunit(sc->sc_dev), num_avail);
306 /* Pull MIN(num_avail, cnt) words from the FIFO */
307 num_words = (num_avail > cnt) ? cnt : num_avail;
308 bcm2835_rng_read_multi4(sc, RNG_DATA, dest,
314 cnt = nread * sizeof(uint32_t);
316 random_harvest_queue(sc->sc_buf, cnt, cnt * NBBY / 2,
317 RANDOM_PURE_BROADCOM);
319 #if defined(BCM2835_RNG_USE_CALLOUT)
320 callout_reset(&sc->sc_rngto, sc->sc_rnghz, bcm2835_rng_harvest, sc);
325 sysctl_bcm2835_rng_2xspeed(SYSCTL_HANDLER_ARGS)
327 struct bcm2835_rng_softc *sc = arg1;
330 rbg2x = sc->sc_rbg2x;
331 error = sysctl_handle_int(oidp, &rbg2x, 0, req);
334 if (req->newptr == NULL)
336 if (rbg2x == sc->sc_rbg2x)
340 bcm2835_rng_stop(sc);
341 sc->sc_rbg2x = rbg2x;
342 bcm2835_rng_start(sc);
347 #ifdef BCM2835_RNG_DEBUG_REGISTERS
349 sysctl_bcm2835_rng_dump(SYSCTL_HANDLER_ARGS)
352 struct bcm2835_rng_softc *sc = arg1;
355 error = sysctl_wire_old_buffer(req, 0);
358 sbuf_new_for_sysctl(&sb, NULL, 128, req);
359 bcm2835_rng_dump_registers(sc, &sb);
360 error = sbuf_finish(&sb);
367 bcm2835_rng_probe(device_t dev)
370 if (!ofw_bus_status_okay(dev))
373 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
376 device_set_desc(dev, "Broadcom BCM2835 RNG");
378 return (BUS_PROBE_DEFAULT);
382 bcm2835_rng_attach(device_t dev)
384 struct bcm2835_rng_softc *sc;
385 struct sysctl_ctx_list *sysctl_ctx;
386 struct sysctl_oid *sysctl_tree;
390 sc = device_get_softc(dev);
392 sc->sc_stall_count = RNG_STALL_COUNT_DEFAULT;
393 #ifdef BCM2835_RNG_USE_CALLOUT
394 /* Initialize callout */
395 callout_init(&sc->sc_rngto, CALLOUT_MPSAFE);
397 TUNABLE_INT_FETCH("bcmrng.2xspeed", &sc->sc_rbg2x);
398 TUNABLE_INT_FETCH("bcmrng.stall_count", &sc->sc_stall_count);
400 /* Allocate memory resources */
402 sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
404 if (sc->sc_mem_res == NULL) {
405 bcm2835_rng_detach(dev);
409 #if defined(BCM2835_RNG_USE_INTERRUPT)
410 /* Allocate interrupt resource */
412 sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
413 RF_SHAREABLE | RF_ACTIVE);
414 if (sc->sc_irq_res == NULL) {
415 bcm2835_rng_detach(dev);
419 /* Set up the interrupt handler */
420 error = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
421 NULL, (driver_intr_t *)bcm2835_rng_harvest, sc, &sc->sc_intr_hdl);
423 device_printf(dev, "Failed to set up IRQ\n");
424 sc->sc_intr_hdl = NULL;
425 bcm2835_rng_detach(dev);
431 bcm2835_rng_start(sc);
433 /* Dump the registers if booting verbose */
437 (void) sbuf_new(&sb, NULL, 256,
438 SBUF_AUTOEXTEND | SBUF_INCLUDENUL);
439 bcm2835_rng_dump_registers(sc, &sb);
441 error = sbuf_finish(&sb);
443 device_printf(dev, "%s", sbuf_data(&sb));
447 sysctl_ctx = device_get_sysctl_ctx(dev);
448 sysctl_tree = device_get_sysctl_tree(dev);
449 SYSCTL_ADD_LONG(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
450 "underrun", CTLFLAG_RD, &sc->sc_underrun,
451 "Number of FIFO underruns");
452 SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
453 "2xspeed", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
454 sysctl_bcm2835_rng_2xspeed, "I", "Enable RBG 2X SPEED");
455 SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
456 "stall_count", CTLFLAG_RW, &sc->sc_stall_count,
457 RNG_STALL_COUNT_DEFAULT, "Number of underruns to assume RNG stall");
458 #ifdef BCM2835_RNG_DEBUG_REGISTERS
459 SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
460 "dumpregs", CTLTYPE_STRING | CTLFLAG_RD, sc, 0,
461 sysctl_bcm2835_rng_dump, "S", "Dump RNG registers");
464 #if defined(BCM2835_RNG_USE_CALLOUT)
467 sc->sc_rnghz = hz / 100;
470 callout_reset(&sc->sc_rngto, sc->sc_rnghz, bcm2835_rng_harvest, sc);
477 bcm2835_rng_detach(device_t dev)
479 struct bcm2835_rng_softc *sc;
480 #if defined(BCM2835_RNG_USE_INTERRUPT)
484 sc = device_get_softc(dev);
487 bcm2835_rng_stop(sc);
489 /* Drain the callout it */
490 #if defined(BCM2835_RNG_USE_CALLOUT)
491 callout_drain(&sc->sc_rngto);
494 #if defined(BCM2835_RNG_USE_INTERRUPT)
495 /* Tear down the interrupt */
496 if (sc->sc_irq_res && sc->sc_intr_hdl) {
497 error = bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_intr_hdl);
499 device_printf(dev, "could not tear down IRQ\n");
502 sc->sc_intr_hdl = NULL;
505 /* Release interrupt resource */
506 if (sc->sc_irq_res) {
507 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
508 sc->sc_irq_res = NULL;
512 /* Release memory resource */
513 if (sc->sc_mem_res != NULL)
514 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
519 static device_method_t bcm2835_rng_methods[] = {
520 /* Device interface */
521 DEVMETHOD(device_probe, bcm2835_rng_probe),
522 DEVMETHOD(device_attach, bcm2835_rng_attach),
523 DEVMETHOD(device_detach, bcm2835_rng_detach),
528 static driver_t bcm2835_rng_driver = {
531 sizeof(struct bcm2835_rng_softc)
533 static devclass_t bcm2835_rng_devclass;
535 DRIVER_MODULE(bcm2835_rng, simplebus, bcm2835_rng_driver,
536 bcm2835_rng_devclass, 0, 0);
537 DRIVER_MODULE(bcm2835_rng, ofwbus, bcm2835_rng_driver, bcm2835_rng_devclass, 0,
539 MODULE_VERSION(bcm2835_rng, 1);
540 MODULE_DEPEND(bcm2835_rng, randomdev, 1, 1, 1);