Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 19 Jul 2016 19:09:51 +0100
From:      Mark R V Murray <markm@FreeBSD.org>
To:        Mark Robert Vaughan Murray <markm@FreeBSD.org>
Cc:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   Re: svn commit: r303035 - in head/sys: arm/broadcom/bcm2835 boot/fdt/dts/arm sys
Message-ID:  <AAF7744D-871E-4CFC-8DDE-A302C5E71F51@FreeBSD.org>
In-Reply-To: <201607191807.u6JI7lAq099753@repo.freebsd.org>
References:  <201607191807.u6JI7lAq099753@repo.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help

--Apple-Mail=_B71B2847-D9CF-4269-8A6B-B7E495B14AC2
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain;
	charset=us-ascii

Hi *

I'm going to get a bollicking for the formatting in this. Apologies in =
advance!

M

> On 19 Jul 2016, at 19:07, Mark Murray <markm@FreeBSD.org> wrote:
>=20
> Author: markm
> Date: Tue Jul 19 18:07:47 2016
> New Revision: 303035
> URL: https://svnweb.freebsd.org/changeset/base/303035
>=20
> Log:
>  Random bit generator (RBG) driver for RPi and RPi2.
>=20
>  Summary:
>  This driver supports the following methods to trigger gathering =
random bits from the hardware:
>  1. interrupt when the FIFO is full (default) fed into the harvest =
queue
>  2. callout (when BCM2835_RNG_USE_CALLOUT is defined) every second if =
hz is less than 100, otherwise hz / 100, feeding the random bits into =
the harvest queue
>=20
>  If the kernel is booted with verbose enabled, the contents of the =
registers will be dumped after the RBG is started during the attach =
routine.
>=20
>  Author: hackagadget_gmail.com (Stephen J. Kiernan)
>=20
>  Test Plan: Built RPI2 kernel and booted on board. Tested the =
different methods to feed the harvest queue (callout, interrupt) and the =
interrupt driven approach seems best. However, keeping the other method =
for people to be able to experiment with.
>=20
>  Reviewed By: adrian, delphij, markm
>=20
>  Differential Revision: https://reviews.freebsd.org/D6888
>=20
> Added:
>  head/sys/arm/broadcom/bcm2835/bcm2835_rng.c   (contents, props =
changed)
> Modified:
>  head/sys/arm/broadcom/bcm2835/files.bcm283x
>  head/sys/boot/fdt/dts/arm/bcm2835.dtsi
>  head/sys/boot/fdt/dts/arm/bcm2836.dtsi
>  head/sys/sys/random.h
>=20
> Added: head/sys/arm/broadcom/bcm2835/bcm2835_rng.c
> =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
> --- /dev/null	00:00:00 1970	(empty, because file is newly added)
> +++ head/sys/arm/broadcom/bcm2835/bcm2835_rng.c	Tue Jul 19 =
18:07:47 2016	(r303035)
> @@ -0,0 +1,534 @@
> +/*
> + * 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>
> +
> +#if !defined(BCM2835_RNG_USE_CALLOUT)
> +#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;
> +
> +#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))
> +
> +#define	RNG_NUM_OSCILLATORS	6
> +#define	RNG_STALL_COUNT_DEFAULT	10
> +
> +struct bcm2835_rng_softc {
> +	device_t		sc_dev;
> +	struct resource *	sc_mem_res;
> +	struct resource *	sc_irq_res;
> +	void *			sc_intr_hdl;
> +#if defined(BCM2835_RNG_USE_CALLOUT) || =
defined(BCM2835_RNG_USE_INTERRUPT)
> +	uint32_t		sc_buf[RNG_FIFO_WORDS];
> +#endif
> +#if defined(BCM2835_RNG_USE_CALLOUT)
> +	struct callout		sc_rngto;
> +	int			sc_rnghz;
> +#endif
> +	int			sc_stall_count;
> +	int			sc_rbg2x;
> +	long			sc_underrun;
> +};
> +
> +static __inline void
> +bcm2835_rng_stat_inc_underrun(struct bcm2835_rng_softc *sc)
> +{
> +
> +	atomic_add_long(&sc->sc_underrun, 1);
> +}
> +
> +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;
> +	int i;
> +
> +	/* Display RNG control register contents */
> +	val =3D bcm2835_rng_read4(sc, RNG_CTRL);
> +	sbuf_printf(sbp, "RNG_CTRL (%08x)\n", val);
> +
> +	comblk2_osc =3D (val & RNG_COMBLK2_OSC) >> =
RNG_COMBLK2_OSC_SHIFT;
> +	sbuf_printf(sbp, "  RNG_COMBLK2_OSC (%02x)\n", comblk2_osc);
> +	for (i =3D 0; i < RNG_NUM_OSCILLATORS; i++)
> +		if ((comblk2_osc & (1 << i)) =3D=3D 0)
> +			sbuf_printf(sbp, "    Oscillator %d enabled\n", =
i + 1);
> +
> +	comblk1_osc =3D (val & RNG_COMBLK1_OSC) >> =
RNG_COMBLK1_OSC_SHIFT;
> +	sbuf_printf(sbp, "  RNG_COMBLK1_OSC (%02x)\n", comblk1_osc);
> +	for (i =3D 0; i < RNG_NUM_OSCILLATORS; i++)
> +		if ((comblk1_osc & (1 << i)) =3D=3D 0)
> +			sbuf_printf(sbp, "    Oscillator %d enabled\n", =
i + 1);
> +
> +	jclk_byp_div =3D (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) !=3D 0)
> +		sbuf_cat(sbp, "  RNG_RBG2X: RNG 2X SPEED enabled\n");
> +
> +	if ((val & RNG_RBGEN_BIT) !=3D 0)
> +		sbuf_cat(sbp, "  RNG_RBGEN_BIT: RBG enabled\n");
> +
> +	/* Display RNG status register contents */
> +	val =3D 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);
> +
> +	/* Display FIFO threshold register contents */
> +	val =3D bcm2835_rng_read4(sc, RNG_FF_THRES);
> +	sbuf_printf(sbp, "RNG_FF_THRES: %05x\n", val & =
RNG_FF_THRES_MASK);
> +
> +	/* Display interrupt mask register contents */
> +	val =3D bcm2835_rng_read4(sc, RNG_INT_MASK);
> +	sbuf_printf(sbp, "RNG_INT_MASK: interrupt %s\n",
> +	     ((val & RNG_INT_OFF_BIT) !=3D 0) ? "disabled" : "enabled");
> +}
> +
> +static void
> +bcm2835_rng_disable_intr(struct bcm2835_rng_softc *sc)
> +{
> +	uint32_t mask;
> +
> +	/* Set the interrupt off bit in the interrupt mask register */
> +	mask =3D bcm2835_rng_read4(sc, RNG_INT_MASK);
> +	mask |=3D 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;
> +
> +	/* Clear the interrupt off bit in the interrupt mask register */
> +	mask =3D bcm2835_rng_read4(sc, RNG_INT_MASK);
> +	mask &=3D ~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 =3D bcm2835_rng_read4(sc, RNG_CTRL);
> +	ctrl |=3D RNG_RBGEN_BIT;
> +	if (sc->sc_rbg2x)
> +		ctrl |=3D 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 =3D bcm2835_rng_read4(sc, RNG_CTRL);
> +	ctrl &=3D ~RNG_RBGEN_BIT;
> +	bcm2835_rng_write4(sc, RNG_CTRL, ctrl);
> +}
> +
> +static void
> +bcm2835_rng_harvest(struct bcm2835_rng_softc *sc)
> +{
> +	uint32_t *dest;
> +	uint32_t status;
> +	u_int cnt, nread, num_avail, num_words;
> +	int seen_underrun, num_stalls;
> +
> +	dest =3D sc->sc_buf;
> +	nread =3D num_words =3D 0;
> +	seen_underrun =3D num_stalls =3D 0;
> +	for (cnt =3D sizeof(sc->sc_buf) / sizeof(uint32_t); cnt > 0;
> +	    cnt -=3D num_words) {
> +		/* Read status register to find out how many words =
available */
> +		status =3D bcm2835_rng_read4(sc, RNG_STATUS);
> +		num_avail =3D (status >> RND_VAL_SHIFT) & RND_VAL_MASK;
> +
> +		/* If we have none... */
> +		if (num_avail =3D=3D 0) {
> +			bcm2835_rng_stat_inc_underrun(sc);
> +			if (++seen_underrun >=3D sc->sc_stall_count) {
> +				if (num_stalls++ > 0) {
> +					device_printf(sc->sc_dev,
> +					    "RNG stalled, disabling =
device\n");
> +					bcm2835_rng_stop(sc);
> +					break;
> +				} else {
> +					device_printf(sc->sc_dev,
> +					    "Too many underruns, =
resetting\n");
> +					bcm2835_rng_stop(sc);
> +					bcm2835_rng_start(sc);
> +					seen_underrun =3D 0;
> +				}
> +			}
> +			/* Try again */
> +			continue;
> +		}
> +
> +		CTR2(KTR_DEV, "%s: %d words available in RNG FIFO",
> +		    device_get_nameunit(sc->sc_dev), num_avail);
> +
> +		/* Pull MIN(num_avail, cnt) words from the FIFO */
> +		num_words =3D (num_avail > cnt) ? cnt : num_avail;
> +		bcm2835_rng_read_multi4(sc, RNG_DATA, dest,
> +		    num_words);
> +		dest +=3D num_words;
> +		nread +=3D num_words;
> +	}
> +
> +	cnt =3D nread * sizeof(uint32_t);
> +	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
> +}
> +
> +static int
> +sysctl_bcm2835_rng_2xspeed(SYSCTL_HANDLER_ARGS)
> +{
> +	struct bcm2835_rng_softc *sc =3D arg1;
> +	int error, rbg2x;
> +
> +	rbg2x =3D sc->sc_rbg2x;
> +	error =3D sysctl_handle_int(oidp, &rbg2x, 0, req);
> +	if (error)
> +		return (error);
> +	if (req->newptr =3D=3D NULL)
> +		return (error);
> +	if (rbg2x =3D=3D sc->sc_rbg2x)
> +		return (0);
> +
> +	/* Reset the RNG */
> +	bcm2835_rng_stop(sc);
> +	sc->sc_rbg2x =3D 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 =3D arg1;
> +	int error;
> +
> +	error =3D sysctl_wire_old_buffer(req, 0);
> +	if (error !=3D 0)
> +		return (error);
> +	sbuf_new_for_sysctl(&sb, NULL, 128, req);
> +	bcm2835_rng_dump_registers(sc, &sb);
> +        error =3D 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 =3D 0;
> +	sc =3D device_get_softc(dev);
> +	sc->sc_dev =3D dev;
> +	sc->sc_stall_count =3D RNG_STALL_COUNT_DEFAULT;
> +#ifdef BCM2835_RNG_USE_CALLOUT
> +	/* Initialize callout */
> +	callout_init(&sc->sc_rngto, CALLOUT_MPSAFE);
> +#endif
> +	TUNABLE_INT_FETCH("bcmrng.2xspeed", &sc->sc_rbg2x);
> +	TUNABLE_INT_FETCH("bcmrng.stall_count", &sc->sc_stall_count);
> +
> +	/* Allocate memory resources */
> +	rid =3D 0;
> +	sc->sc_mem_res =3D bus_alloc_resource_any(dev, SYS_RES_MEMORY, =
&rid,
> +	    RF_ACTIVE);
> +	if (sc->sc_mem_res =3D=3D NULL) {
> +		bcm2835_rng_detach(dev);
> +		return (ENXIO);
> +	}
> +
> +#if defined(BCM2835_RNG_USE_INTERRUPT)
> +	/* Allocate interrupt resource */
> +	rid =3D 0;
> +	sc->sc_irq_res =3D bus_alloc_resource_any(dev, SYS_RES_IRQ, =
&rid,
> +	    RF_SHAREABLE | RF_ACTIVE);
> +	if (sc->sc_irq_res =3D=3D NULL) {
> +		bcm2835_rng_detach(dev);
> +		return (ENXIO);
> +	}
> +
> +	/* Set up the interrupt handler */
> +	error =3D 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 =3D NULL;
> +		bcm2835_rng_detach(dev);
> +		return (error);
> +	}
> +#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 =3D sbuf_finish(&sb);
> +		if (error =3D=3D 0)
> +			device_printf(dev, "%s", sbuf_data(&sb));
> +		sbuf_delete(&sb);
> +	}
> +
> +	sysctl_ctx =3D device_get_sysctl_ctx(dev);
> +	sysctl_tree =3D device_get_sysctl_tree(dev);
> +	SYSCTL_ADD_LONG(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), =
OID_AUTO,
> +	    "underrun", CTLFLAG_RD, &sc->sc_underrun,
> +	    "Number of FIFO underruns");
> +	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");
> +	SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), =
OID_AUTO,
> +	    "stall_count", CTLFLAG_RW, &sc->sc_stall_count,
> +	    RNG_STALL_COUNT_DEFAULT, "Number of underruns to assume RNG =
stall");
> +#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)
> +	/* Reset callout */
> +	if (hz >=3D 100)
> +		sc->sc_rnghz =3D hz / 100;
> +	else
> +		sc->sc_rnghz =3D 1;
> +	callout_reset(&sc->sc_rngto, sc->sc_rnghz, bcm2835_rng_harvest, =
sc);
> +#endif
> +
> +	return (0);
> +}
> +
> +static int
> +bcm2835_rng_detach(device_t dev)
> +{
> +	struct bcm2835_rng_softc *sc;
> +#if defined(BCM2835_RNG_USE_INTERRUPT)
> +	int error;
> +#endif
> +
> +	sc =3D device_get_softc(dev);
> +
> +	/* Stop the RNG */
> +	bcm2835_rng_stop(sc);
> +
> +	/* Drain the callout it */
> +#if defined(BCM2835_RNG_USE_CALLOUT)
> +	callout_drain(&sc->sc_rngto);
> +#endif
> +
> +#if defined(BCM2835_RNG_USE_INTERRUPT)
> +	/* Tear down the interrupt */
> +	if (sc->sc_irq_res && sc->sc_intr_hdl) {
> +		error =3D bus_teardown_intr(dev, sc->sc_irq_res, =
sc->sc_intr_hdl);
> +		if (error !=3D 0) {
> +			device_printf(dev, "could not tear down IRQ\n");
> +			return (error);
> +		}
> +		sc->sc_intr_hdl =3D 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 =3D NULL;
> +	}
> +#endif
> +
> +	/* Release memory resource */
> +	if (sc->sc_mem_res !=3D NULL)
> +		bus_release_resource(dev, SYS_RES_MEMORY, 0, =
sc->sc_mem_res);
> +
> +	return (0);
> +}
> +
> +static device_method_t bcm2835_rng_methods[] =3D {
> +	/* 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 =3D {
> +	"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);
>=20
> Modified: head/sys/arm/broadcom/bcm2835/files.bcm283x
> =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
> --- head/sys/arm/broadcom/bcm2835/files.bcm283x	Tue Jul 19 =
18:05:25 2016	(r303034)
> +++ head/sys/arm/broadcom/bcm2835/files.bcm283x	Tue Jul 19 =
18:07:47 2016	(r303035)
> @@ -10,6 +10,7 @@ arm/broadcom/bcm2835/bcm2835_gpio.c		opt
> 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		optional random
> arm/broadcom/bcm2835/bcm2835_sdhci.c		optional sdhci
> arm/broadcom/bcm2835/bcm2835_spi.c		optional bcm2835_spi
> arm/broadcom/bcm2835/bcm2835_vcio.c		standard
>=20
> Modified: head/sys/boot/fdt/dts/arm/bcm2835.dtsi
> =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
> --- head/sys/boot/fdt/dts/arm/bcm2835.dtsi	Tue Jul 19 18:05:25 2016	=
(r303034)
> +++ head/sys/boot/fdt/dts/arm/bcm2835.dtsi	Tue Jul 19 18:07:47 2016	=
(r303035)
> @@ -396,6 +396,14 @@
> 			};
> 		};
>=20
> +		rng {
> +			compatible =3D "broadcom,bcm2835-rng",
> +				     "broadcom,bcm2708-rng";
> +			reg =3D <0x104000 0x20>;
> +			interrupts =3D <69>;
> +			interrupt-parent =3D <&intc>;
> +		};
> +
> 		bsc0 {
> 			#address-cells =3D <1>;
> 			#size-cells =3D <0>;
>=20
> Modified: head/sys/boot/fdt/dts/arm/bcm2836.dtsi
> =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
> --- head/sys/boot/fdt/dts/arm/bcm2836.dtsi	Tue Jul 19 18:05:25 2016	=
(r303034)
> +++ head/sys/boot/fdt/dts/arm/bcm2836.dtsi	Tue Jul 19 18:07:47 2016	=
(r303035)
> @@ -389,6 +389,14 @@
> 			};
> 		};
>=20
> +		rng {
> +			compatible =3D "broadcom,bcm2835-rng",
> +				     "broadcom,bcm2708-rng";
> +			reg =3D <0x104000 0x20>;
> +			interrupts =3D <69>;
> +			interrupt-parent =3D <&intc>;
> +		};
> +
> 		bsc0 {
> 			#address-cells =3D <1>;
> 			#size-cells =3D <0>;
>=20
> Modified: head/sys/sys/random.h
> =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
> --- head/sys/sys/random.h	Tue Jul 19 18:05:25 2016	=
(r303034)
> +++ head/sys/sys/random.h	Tue Jul 19 18:07:47 2016	=
(r303035)
> @@ -90,6 +90,7 @@ enum random_entropy_source {
> 	RANDOM_PURE_NEHEMIAH,
> 	RANDOM_PURE_RNDTEST,
> 	RANDOM_PURE_VIRTIO,
> +	RANDOM_PURE_BROADCOM,
> 	ENTROPYSOURCE
> };
>=20
>=20

--
Mark R V Murray


--Apple-Mail=_B71B2847-D9CF-4269-8A6B-B7E495B14AC2
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
	filename=signature.asc
Content-Type: application/pgp-signature;
	name=signature.asc
Content-Description: Message signed with OpenPGP using GPGMail

-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.30
Comment: GPGTools - http://gpgtools.org

iEYEARECAAYFAleObPUACgkQzQuKNftX15Ow7gCgpqW4NCMmkhQci4TOSrj/mFzK
dmIAnjNBi+ycgdd/b8kJNbh3oMnj6NX6
=X9dj
-----END PGP SIGNATURE-----

--Apple-Mail=_B71B2847-D9CF-4269-8A6B-B7E495B14AC2--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?AAF7744D-871E-4CFC-8DDE-A302C5E71F51>