Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F152639019
D6888.id17681.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
18 KB
Referenced Files
None
Subscribers
None
D6888.id17681.diff
View Options
Index: sys/arm/broadcom/bcm2835/bcm2835_rng.c
===================================================================
--- /dev/null
+++ sys/arm/broadcom/bcm2835/bcm2835_rng.c
@@ -0,0 +1,580 @@
+/*
+ * Copyright (c) 2015, 2016, Stephen J. Kiernan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/random.h>
+#include <sys/sbuf.h>
+#include <sys/sysctl.h>
+#include <sys/selinfo.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/random/randomdev.h>
+#include <dev/random/random_harvestq.h>
+
+#define BCM2835_RNG_REGISTER_SOURCE
+
+#if defined(BCM2835_RNG_USE_CALLOUT) && defined(BCM2835_RNG_REGISTER_SOURCE)
+#error BCM2835_RNG_USE_CALLOUT and BCM2835_RNG_REGISTER_SOURCE are mutually exclusive
+#endif
+
+#if !defined(BCM2835_RNG_USE_CALLOUT) && !defined(BCM2835_RNG_REGISTER_SOURCE)
+#define BCM2835_RNG_USE_INTERRUPT
+#endif
+
+static device_attach_t bcm2835_rng_attach;
+static device_detach_t bcm2835_rng_detach;
+static device_probe_t bcm2835_rng_probe;
+
+#ifdef BCM2835_RNG_REGISTER_SOURCE
+static u_int bcm2835_rng_source_read(void *, u_int);
+#endif
+
+#define RNG_CTRL 0x00 /* RNG Control Register */
+#define RNG_COMBLK1_OSC 0x003f0000 /* Combiner Blk 1 Oscillator */
+#define RNG_COMBLK1_OSC_SHIFT 16
+#define RNG_COMBLK2_OSC 0x0fc00000 /* Combiner Blk 2 Oscillator */
+#define RNG_COMBLK2_OSC_SHIFT 22
+#define RNG_JCLK_BYP_DIV_CNT 0x0000ff00 /* Jitter clk bypass divider
+ count */
+#define RNG_JCLK_BYP_DIV_CNT_SHIFT 8
+#define RNG_JCLK_BYP_SRC 0x00000020 /* Jitter clk bypass source */
+#define RNG_JCLK_BYP_SEL 0x00000010 /* Jitter clk bypass select */
+#define RNG_RBG2X 0x00000002 /* RBG 2X SPEED */
+#define RNG_RBGEN_BIT 0x00000001 /* Enable RNG bit */
+#define RNG_STATUS 0x04 /* RNG status register */
+#define RND_VAL_SHIFT 24 /* Shift for valid words */
+#define RND_VAL_MASK 0x000000ff /* Number valid words mask */
+#define RND_VAL_WARM_CNT 0x40000 /* RNG Warm Up count */
+#define RND_WARM_CNT 0xfffff /* RNG Warm Up Count mask */
+#define RNG_DATA 0x08 /* RNG Data Register */
+#define RNG_FF_THRES 0x0c
+#define RNG_FF_THRES_MASK 0x0000001f
+#define RNG_INT_MASK 0x10
+#define RNG_INT_OFF_BIT 0x00000001
+
+#define RNG_FF_DEFAULT 0x10 /* FIFO threshold default */
+
+#define RNG_FIFO_WORDS (RNG_FF_DEFAULT / sizeof(uint32_t))
+
+struct bcm2835_rng_softc {
+ device_t sc_dev;
+ struct resource * sc_mem_res;
+ struct resource * sc_irq_res;
+ void * sc_intr_hdl;
+ uint32_t sc_flags;
+#if defined(BCM2835_RNG_USE_CALLOUT) || defined(BCM2835_RNG_USE_INTERRUPT)
+ uint32_t sc_buf[RNG_FIFO_WORDS];
+#endif
+ int sc_rbg2x;
+#if defined(BCM2835_RNG_USE_CALLOUT)
+ struct callout sc_rngto;
+ int sc_rnghz;
+#endif
+#define BCMRNG_SRC_REG (1 << 0)
+ struct {
+ long underrun;
+ } sc_stats;
+};
+
+#if defined(BCM2835_RNG_REGISTER_SOURCE)
+static struct random_source bcm2835_rng_source = {
+ .rs_ident = "Broadcom BCM2835 RNG",
+ .rs_source = RANDOM_PURE_BROADCOM,
+ .rs_read = bcm2835_rng_source_read
+};
+#endif
+
+#define BCM_RNG_INC_STAT(_sc, _stat) \
+ do { \
+ atomic_add_long(&(_sc)->sc_stats._stat, 1); \
+ } while(0)
+
+static struct bcm2835_rng_softc *bcm2835_rng_sc;
+
+static __inline uint32_t
+bcm2835_rng_read4(struct bcm2835_rng_softc *sc, bus_size_t off)
+{
+
+ return bus_read_4(sc->sc_mem_res, off);
+}
+
+static __inline void
+bcm2835_rng_read_multi4(struct bcm2835_rng_softc *sc, bus_size_t off,
+ uint32_t *datap, bus_size_t count)
+{
+
+ bus_read_multi_4(sc->sc_mem_res, off, datap, count);
+}
+
+static __inline void
+bcm2835_rng_write4(struct bcm2835_rng_softc *sc, bus_size_t off, uint32_t val)
+{
+
+ bus_write_4(sc->sc_mem_res, off, val);
+}
+
+static void
+bcm2835_rng_dump_registers(struct bcm2835_rng_softc *sc, struct sbuf *sbp)
+{
+ uint32_t comblk2_osc, comblk1_osc, jclk_byp_div, val;
+
+ val = bcm2835_rng_read4(sc, RNG_CTRL);
+ sbuf_printf(sbp, "RNG_CTRL (%08x)\n", val);
+ comblk2_osc = (val & RNG_COMBLK2_OSC) >> RNG_COMBLK2_OSC_SHIFT;
+ sbuf_printf(sbp, " RNG_COMBLK2_OSC (%02x)\n", comblk2_osc);
+ if ((comblk2_osc & 0x2) == 0)
+ sbuf_cat(sbp, " Oscillator 1 enabled\n");
+ if ((comblk2_osc & 0x2) == 0)
+ sbuf_cat(sbp, " Oscillator 2 enabled\n");
+ if ((comblk2_osc & 0x4) == 0)
+ sbuf_cat(sbp, " Oscillator 3 enabled\n");
+ if ((comblk2_osc & 0x8) == 0)
+ sbuf_cat(sbp, " Oscillator 4 enabled\n");
+ if ((comblk2_osc & 0x10) == 0)
+ sbuf_cat(sbp, " Oscillator 5 enabled\n");
+ if ((comblk2_osc & 0x20) == 0)
+ sbuf_cat(sbp, " Oscillator 6 enabled\n");
+ comblk1_osc = (val & RNG_COMBLK1_OSC) >> RNG_COMBLK1_OSC_SHIFT;
+ sbuf_printf(sbp, " RNG_COMBLK1_OSC (%02x)\n", comblk1_osc);
+ if ((comblk1_osc & 0x1) == 0)
+ sbuf_cat(sbp, " Oscillator 1 enabled\n");
+ if ((comblk1_osc & 0x2) == 0)
+ sbuf_cat(sbp, " Oscillator 2 enabled\n");
+ if ((comblk1_osc & 0x4) == 0)
+ sbuf_cat(sbp, " Oscillator 3 enabled\n");
+ if ((comblk1_osc & 0x8) == 0)
+ sbuf_cat(sbp, " Oscillator 4 enabled\n");
+ if ((comblk1_osc & 0x10) == 0)
+ sbuf_cat(sbp, " Oscillator 5 enabled\n");
+ if ((comblk1_osc & 0x20) == 0)
+ sbuf_cat(sbp, " Oscillator 6 enabled\n");
+ jclk_byp_div = (val & RNG_JCLK_BYP_DIV_CNT) >>
+ RNG_JCLK_BYP_DIV_CNT_SHIFT;
+ sbuf_printf(sbp,
+ " RNG_JCLK_BYP_DIV_CNT (%02x)\n APB clock frequency / %d\n",
+ jclk_byp_div, 2 * (jclk_byp_div + 1));
+ sbuf_printf(sbp, " RNG_JCLK_BYP_SRC:\n %s\n",
+ (val & RNG_JCLK_BYP_SRC) ? "Use divided down APB clock" :
+ "Use RNG clock (APB clock)");
+ sbuf_printf(sbp, " RNG_JCLK_BYP_SEL:\n %s\n",
+ (val & RNG_JCLK_BYP_SEL) ? "Bypass internal jitter clock" :
+ "Use internal jitter clock");
+ if ((val & RNG_RBG2X) != 0)
+ sbuf_cat(sbp, " RNG_RBG2X: RNG 2X SPEED enabled\n");
+ if ((val & RNG_RBGEN_BIT) != 0)
+ sbuf_cat(sbp, " RNG_RBGEN_BIT: RBG enabled\n");
+
+ val = bcm2835_rng_read4(sc, RNG_STATUS);
+ sbuf_printf(sbp, "RNG_CTRL (%08x)\n", val);
+ sbuf_printf(sbp, " RND_VAL: %02x\n",
+ (val >> RND_VAL_SHIFT) & RND_VAL_MASK);
+ sbuf_printf(sbp, " RND_WARM_CNT: %05x\n", val & RND_WARM_CNT);
+
+ val = bcm2835_rng_read4(sc, RNG_FF_THRES);
+ sbuf_printf(sbp, "RNG_FF_THRES: %05x\n", val & RNG_FF_THRES_MASK);
+
+ val = bcm2835_rng_read4(sc, RNG_INT_MASK);
+ sbuf_printf(sbp, "RNG_INT_MASK: interrupt %s\n",
+ ((val & RNG_INT_OFF_BIT) != 0) ? "disabled" : "enabled");
+}
+
+static u_int
+bcm2835_rng_read(struct bcm2835_rng_softc *sc, void *buf, u_int cnt)
+{
+ uint32_t *dest;
+ uint32_t status;
+ u_long num_words;
+ u_int nread;
+ int count, num_avail;
+#if defined(BCM2835_RNG_CHECK_UNDERRUN)
+ int seen_underrun;
+#endif
+
+ KASSERT(cnt % sizeof(uint32_t) == 0, ("partial read %u", cnt));
+
+ dest = buf;
+ nread = 0;
+ num_words = 0;
+ for (count = cnt / sizeof(uint32_t); count > 0; count -= num_words) {
+ /* Read status register to find out how many words available */
+ status = bcm2835_rng_read4(sc, RNG_STATUS);
+ num_avail = (status >> RND_VAL_SHIFT) & RND_VAL_MASK;
+
+ /* If we have none... */
+ if (num_avail == 0) {
+ BCM_RNG_INC_STAT(sc, underrun);
+#if defined(BCM2835_RNG_CHECK_UNDERRUN)
+ if (++seen_underrun >= 10)
+ panic("Too many underruns, RNG stalled?");
+#endif
+#if defined(BCM2835_RNG_USE_CALLOUT)
+ break; /* Just return */
+#else
+ if (nread > 0)
+ break; /* We read something, just return */
+
+ DELAY(1000); /* Wait 1ms and retry */
+ continue;
+#endif
+ }
+
+ CTR2(KTR_DEV, "%s: %d words available in RNG FIFO",
+ device_get_nameunit(sc->sc_dev), num_avail);
+
+ /* Pull MIN(num_avail, count) words from the FIFO */
+ num_words = (num_avail > count) ? count : num_avail;
+ bcm2835_rng_read_multi4(sc, RNG_DATA, dest,
+ num_words);
+ dest += num_words;
+ nread += num_words;
+ }
+
+ return (nread * sizeof(uint32_t));
+}
+
+#ifdef BCM2835_RNG_REGISTER_SOURCE
+static u_int
+bcm2835_rng_source_read(void *buf, u_int cnt)
+{
+
+ return (bcm2835_rng_read(bcm2835_rng_sc, buf, cnt));
+}
+#endif
+
+static void
+bcm2835_rng_disable_intr(struct bcm2835_rng_softc *sc)
+{
+ uint32_t mask;
+
+ mask = bcm2835_rng_read4(sc, RNG_INT_MASK);
+ mask |= RNG_INT_OFF_BIT;
+ bcm2835_rng_write4(sc, RNG_INT_MASK, mask);
+}
+
+#if defined(BCM2835_RNG_USE_INTERRUPT)
+static void
+bcm2835_rng_enable_intr(struct bcm2835_rng_softc *sc)
+{
+ uint32_t mask;
+
+ mask = bcm2835_rng_read4(sc, RNG_INT_MASK);
+ mask &= ~RNG_INT_OFF_BIT;
+ bcm2835_rng_write4(sc, RNG_INT_MASK, mask);
+}
+#endif
+
+static void
+bcm2835_rng_start(struct bcm2835_rng_softc *sc)
+{
+ uint32_t ctrl;
+
+ /* Disable the interrupt */
+ bcm2835_rng_disable_intr(sc);
+
+ /* Set the warmup count */
+ bcm2835_rng_write4(sc, RNG_STATUS, RND_VAL_WARM_CNT);
+
+ /* Enable the RNG */
+ ctrl = bcm2835_rng_read4(sc, RNG_CTRL);
+ ctrl |= RNG_RBGEN_BIT;
+ if (sc->sc_rbg2x)
+ ctrl |= RNG_RBG2X;
+ bcm2835_rng_write4(sc, RNG_CTRL, ctrl);
+
+#if defined(BCM2835_RNG_USE_INTERRUPT)
+ /* Enable the interrupt */
+ bcm2835_rng_enable_intr(sc);
+#endif
+}
+
+static void
+bcm2835_rng_stop(struct bcm2835_rng_softc *sc)
+{
+ uint32_t ctrl;
+
+ /* Disable the RNG */
+ ctrl = bcm2835_rng_read4(sc, RNG_CTRL);
+ ctrl &= ~RNG_RBGEN_BIT;
+ bcm2835_rng_write4(sc, RNG_CTRL, ctrl);
+}
+
+#if defined(BCM2835_RNG_USE_CALLOUT) || defined(BCM2835_RNG_USE_INTERRUPT)
+static void
+bcm2835_rng_harvest(struct bcm2835_rng_softc *sc)
+{
+ u_int cnt;
+
+ cnt = bcm2835_rng_read(sc, sc->sc_buf, sizeof(sc->sc_buf));
+ if (cnt > 0)
+ random_harvest_queue(sc->sc_buf, cnt, cnt * NBBY / 2,
+ RANDOM_PURE_BROADCOM);
+
+#if defined(BCM2835_RNG_USE_CALLOUT)
+ callout_reset(&sc->sc_rngto, sc->sc_rnghz, bcm2835_rng_harvest, sc);
+#endif
+}
+#endif
+
+static int
+sysctl_bcm2835_rng_2xspeed(SYSCTL_HANDLER_ARGS)
+{
+ struct bcm2835_rng_softc *sc = arg1;
+ int error, rbg2x;
+
+ rbg2x = sc->sc_rbg2x;
+ error = sysctl_handle_int(oidp, &rbg2x, 0, req);
+ if (error)
+ return (error);
+ if (req->newptr == NULL)
+ return (error);
+ if (rbg2x == sc->sc_rbg2x)
+ return (0);
+
+ /* Reset the RNG */
+ bcm2835_rng_stop(sc);
+ sc->sc_rbg2x = rbg2x;
+ bcm2835_rng_start(sc);
+
+ return (0);
+}
+
+#ifdef BCM2835_RNG_DEBUG_REGISTERS
+static int
+sysctl_bcm2835_rng_dump(SYSCTL_HANDLER_ARGS)
+{
+ struct sbuf sb;
+ struct bcm2835_rng_softc *sc = arg1;
+ int error;
+
+ error = sysctl_wire_old_buffer(req, 0);
+ if (error != 0)
+ return (error);
+ sbuf_new_for_sysctl(&sb, NULL, 128, req);
+ bcm2835_rng_dump_registers(sc, &sb);
+ error = sbuf_finish(&sb);
+ sbuf_delete(&sb);
+ return (error);
+}
+#endif
+
+static int
+bcm2835_rng_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "broadcom,bcm2835-rng"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Broadcom BCM2835 RNG");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+bcm2835_rng_attach(device_t dev)
+{
+ struct bcm2835_rng_softc *sc;
+ struct sysctl_ctx_list *sysctl_ctx;
+ struct sysctl_oid *sysctl_tree;
+ int error, rid;
+
+ error = 0;
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+ TUNABLE_INT_FETCH("bcmrng.2xspeed", &sc->sc_rbg2x);
+
+ bcm2835_rng_sc = sc;
+
+ /* Allocate memory resources */
+ rid = 0;
+ sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->sc_mem_res == NULL) {
+ error = ENXIO;
+ goto out;
+ }
+
+#if defined(BCM2835_RNG_USE_INTERRUPT)
+ /* Allocate interrupt resource */
+ rid = 0;
+ sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_SHAREABLE | RF_ACTIVE);
+ if (sc->sc_irq_res == NULL) {
+ error = ENXIO;
+ goto out;
+ }
+
+ /* Set up the interrupt handler */
+ error = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
+ NULL, (driver_intr_t *)bcm2835_rng_harvest, sc, &sc->sc_intr_hdl);
+ if (error) {
+ device_printf(dev, "Failed to set up IRQ\n");
+ sc->sc_intr_hdl = NULL;
+ goto out;
+ }
+#endif
+
+ /* Start the RNG */
+ bcm2835_rng_start(sc);
+
+ /* Dump the registers if booting verbose */
+ if (bootverbose) {
+ struct sbuf sb;
+
+ (void) sbuf_new(&sb, NULL, 256,
+ SBUF_AUTOEXTEND | SBUF_INCLUDENUL);
+ bcm2835_rng_dump_registers(sc, &sb);
+ sbuf_trim(&sb);
+ error = sbuf_finish(&sb);
+ if (error == 0)
+ device_printf(dev, "%s", sbuf_data(&sb));
+ sbuf_delete(&sb);
+ }
+
+ sysctl_ctx = device_get_sysctl_ctx(dev);
+ sysctl_tree = device_get_sysctl_tree(dev);
+ SYSCTL_ADD_LONG(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
+ "underrun", CTLFLAG_RD, &sc->sc_stats.underrun,
+ "Number of FIFO underrun");
+ SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
+ "2xspeed", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
+ sysctl_bcm2835_rng_2xspeed, "I", "Enable RBG 2X SPEED");
+#ifdef BCM2835_RNG_DEBUG_REGISTERS
+ SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
+ "dumpregs", CTLTYPE_STRING | CTLFLAG_RD, sc, 0,
+ sysctl_bcm2835_rng_dump, "S", "Dump RNG registers");
+#endif
+
+#if defined(BCM2835_RNG_USE_CALLOUT)
+ /* Initialize and reset callout */
+ if (hz >= 100)
+ sc->sc_rnghz = hz / 100;
+ else
+ sc->sc_rnghz = 1;
+ callout_init(&sc->sc_rngto, CALLOUT_MPSAFE);
+ callout_reset(&sc->sc_rngto, sc->sc_rnghz, bcm2835_rng_harvest, sc);
+#elif defined(BCM2835_RNG_REGISTER_SOURCE)
+ random_source_register(&bcm2835_rng_source);
+#endif
+ sc->sc_flags |= BCMRNG_SRC_REG;
+
+out:
+ if (error)
+ bcm2835_rng_detach(dev);
+
+ return (error);
+}
+
+static int
+bcm2835_rng_detach(device_t dev)
+{
+ struct bcm2835_rng_softc *sc;
+#if defined(BCM2835_RNG_USE_INTERRUPT)
+ int error;
+#endif
+
+ sc = device_get_softc(dev);
+
+ /* Stop the RNG */
+ bcm2835_rng_stop(sc);
+
+ /* If initialized callout, stop it */
+ if (sc->sc_flags & BCMRNG_SRC_REG) {
+#if defined(BCM2835_RNG_USE_CALLOUT)
+ callout_stop(&sc->sc_rngto);
+#elif defined(BCM2835_RNG_REGISTER_SOURCE)
+ random_source_deregister(&bcm2835_rng_source);
+#endif
+ sc->sc_flags &= ~BCMRNG_SRC_REG;
+ }
+
+#if defined(BCM2835_RNG_USE_INTERRUPT)
+ /* Tear down the interrupt */
+ if (sc->sc_irq_res && sc->sc_intr_hdl) {
+ error = bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_intr_hdl);
+ if (error != 0) {
+ device_printf(dev, "could not tear down IRQ\n");
+ return (error);
+ }
+ sc->sc_intr_hdl = NULL;
+ }
+
+ /* Release interrupt resource */
+ if (sc->sc_irq_res) {
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
+ sc->sc_irq_res = NULL;
+ }
+#endif
+
+ /* Release memory resource */
+ if (sc->sc_mem_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+
+ bcm2835_rng_sc = NULL;
+ return (0);
+}
+
+static device_method_t bcm2835_rng_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, bcm2835_rng_probe),
+ DEVMETHOD(device_attach, bcm2835_rng_attach),
+ DEVMETHOD(device_detach, bcm2835_rng_detach),
+
+ DEVMETHOD_END
+};
+
+static driver_t bcm2835_rng_driver = {
+ "bcmrng",
+ bcm2835_rng_methods,
+ sizeof(struct bcm2835_rng_softc)
+};
+static devclass_t bcm2835_rng_devclass;
+
+DRIVER_MODULE(bcm2835_rng, simplebus, bcm2835_rng_driver,
+ bcm2835_rng_devclass, 0, 0);
+DRIVER_MODULE(bcm2835_rng, ofwbus, bcm2835_rng_driver, bcm2835_rng_devclass, 0,
+ 0);
+MODULE_VERSION(bcm2835_rng, 1);
+MODULE_DEPEND(bcm2835_rng, randomdev, 1, 1, 1);
Index: sys/arm/broadcom/bcm2835/files.bcm283x
===================================================================
--- sys/arm/broadcom/bcm2835/files.bcm283x
+++ sys/arm/broadcom/bcm2835/files.bcm283x
@@ -10,6 +10,7 @@
arm/broadcom/bcm2835/bcm2835_intr.c standard
arm/broadcom/bcm2835/bcm2835_machdep.c standard
arm/broadcom/bcm2835/bcm2835_mbox.c standard
+arm/broadcom/bcm2835/bcm2835_rng.c standard
arm/broadcom/bcm2835/bcm2835_sdhci.c optional sdhci
arm/broadcom/bcm2835/bcm2835_spi.c optional bcm2835_spi
arm/broadcom/bcm2835/bcm2835_vcio.c standard
Index: sys/boot/fdt/dts/arm/bcm2835.dtsi
===================================================================
--- sys/boot/fdt/dts/arm/bcm2835.dtsi
+++ sys/boot/fdt/dts/arm/bcm2835.dtsi
@@ -396,6 +396,14 @@
};
};
+ rng {
+ compatible = "broadcom,bcm2835-rng",
+ "broadcom,bcm2708-rng";
+ reg = <0x104000 0x20>;
+ interrupts = <69>;
+ interrupt-parent = <&intc>;
+ };
+
bsc0 {
#address-cells = <1>;
#size-cells = <0>;
Index: sys/boot/fdt/dts/arm/bcm2836.dtsi
===================================================================
--- sys/boot/fdt/dts/arm/bcm2836.dtsi
+++ sys/boot/fdt/dts/arm/bcm2836.dtsi
@@ -389,6 +389,14 @@
};
};
+ rng {
+ compatible = "broadcom,bcm2835-rng",
+ "broadcom,bcm2708-rng";
+ reg = <0x104000 0x20>;
+ interrupts = <69>;
+ interrupt-parent = <&intc>;
+ };
+
bsc0 {
#address-cells = <1>;
#size-cells = <0>;
Index: sys/sys/random.h
===================================================================
--- sys/sys/random.h
+++ sys/sys/random.h
@@ -90,6 +90,7 @@
RANDOM_PURE_NEHEMIAH,
RANDOM_PURE_RNDTEST,
RANDOM_PURE_VIRTIO,
+ RANDOM_PURE_BROADCOM,
ENTROPYSOURCE
};
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Apr 17, 4:55 AM (3 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31640239
Default Alt Text
D6888.id17681.diff (18 KB)
Attached To
Mode
D6888: Random bit generator (RBG) driver for RPi and RPi2.
Attached
Detach File
Event Timeline
Log In to Comment