1210311Sjmallett/*- 2210311Sjmallett * Copyright (c) 2010 Juli Mallett <jmallett@FreeBSD.org> 3210311Sjmallett * All rights reserved. 4210311Sjmallett * 5210311Sjmallett * Redistribution and use in source and binary forms, with or without 6210311Sjmallett * modification, are permitted provided that the following conditions 7210311Sjmallett * are met: 8210311Sjmallett * 1. Redistributions of source code must retain the above copyright 9210311Sjmallett * notice, this list of conditions and the following disclaimer. 10210311Sjmallett * 2. Redistributions in binary form must reproduce the above copyright 11210311Sjmallett * notice, this list of conditions and the following disclaimer in the 12210311Sjmallett * documentation and/or other materials provided with the distribution. 13210311Sjmallett * 14210311Sjmallett * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15210311Sjmallett * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16210311Sjmallett * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17210311Sjmallett * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18210311Sjmallett * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19210311Sjmallett * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20210311Sjmallett * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21210311Sjmallett * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22210311Sjmallett * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23210311Sjmallett * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24210311Sjmallett * SUCH DAMAGE. 25210311Sjmallett * 26210311Sjmallett * $FreeBSD: releng/10.2/sys/mips/cavium/octeon_rnd.c 265999 2014-05-14 01:35:43Z ian $ 27210311Sjmallett */ 28210311Sjmallett 29210311Sjmallett#include <sys/cdefs.h> 30210311Sjmallett__FBSDID("$FreeBSD: releng/10.2/sys/mips/cavium/octeon_rnd.c 265999 2014-05-14 01:35:43Z ian $"); 31210311Sjmallett 32210311Sjmallett#include <sys/param.h> 33210311Sjmallett#include <sys/systm.h> 34210311Sjmallett#include <sys/bus.h> 35210311Sjmallett#include <sys/clock.h> 36210311Sjmallett#include <sys/kernel.h> 37210311Sjmallett#include <sys/lock.h> 38210311Sjmallett#include <sys/module.h> 39210311Sjmallett#include <sys/random.h> 40210311Sjmallett 41210311Sjmallett#include <contrib/octeon-sdk/cvmx.h> 42210311Sjmallett#include <contrib/octeon-sdk/cvmx-rng.h> 43210311Sjmallett 44210311Sjmallett#define OCTEON_RND_WORDS 2 45210311Sjmallett 46210311Sjmallettstruct octeon_rnd_softc { 47210311Sjmallett uint64_t sc_entropy[OCTEON_RND_WORDS]; 48210311Sjmallett struct callout sc_callout; 49210311Sjmallett}; 50210311Sjmallett 51210311Sjmallettstatic void octeon_rnd_identify(driver_t *drv, device_t parent); 52210311Sjmallettstatic int octeon_rnd_attach(device_t dev); 53210311Sjmallettstatic int octeon_rnd_probe(device_t dev); 54210311Sjmallettstatic int octeon_rnd_detach(device_t dev); 55210311Sjmallett 56210311Sjmallettstatic void octeon_rnd_harvest(void *); 57210311Sjmallett 58210311Sjmallettstatic device_method_t octeon_rnd_methods[] = { 59210311Sjmallett /* Device interface */ 60210311Sjmallett DEVMETHOD(device_identify, octeon_rnd_identify), 61210311Sjmallett DEVMETHOD(device_probe, octeon_rnd_probe), 62210311Sjmallett DEVMETHOD(device_attach, octeon_rnd_attach), 63210311Sjmallett DEVMETHOD(device_detach, octeon_rnd_detach), 64210311Sjmallett 65210311Sjmallett { 0, 0 } 66210311Sjmallett}; 67210311Sjmallett 68210311Sjmallettstatic driver_t octeon_rnd_driver = { 69210311Sjmallett "rnd", 70210311Sjmallett octeon_rnd_methods, 71210311Sjmallett sizeof (struct octeon_rnd_softc) 72210311Sjmallett}; 73210311Sjmallettstatic devclass_t octeon_rnd_devclass; 74210311SjmallettDRIVER_MODULE(rnd, nexus, octeon_rnd_driver, octeon_rnd_devclass, 0, 0); 75210311Sjmallett 76210311Sjmallettstatic void 77210311Sjmallettocteon_rnd_identify(driver_t *drv, device_t parent) 78210311Sjmallett{ 79210311Sjmallett BUS_ADD_CHILD(parent, 0, "rnd", 0); 80210311Sjmallett} 81210311Sjmallett 82210311Sjmallettstatic int 83210311Sjmallettocteon_rnd_probe(device_t dev) 84210311Sjmallett{ 85210311Sjmallett if (device_get_unit(dev) != 0) 86210311Sjmallett return (ENXIO); 87210311Sjmallett 88210311Sjmallett device_set_desc(dev, "Cavium Octeon Random Number Generator"); 89265999Sian return (BUS_PROBE_NOWILDCARD); 90210311Sjmallett} 91210311Sjmallett 92210311Sjmallettstatic int 93210311Sjmallettocteon_rnd_attach(device_t dev) 94210311Sjmallett{ 95210311Sjmallett struct octeon_rnd_softc *sc; 96210311Sjmallett 97210311Sjmallett sc = device_get_softc(dev); 98210311Sjmallett callout_init(&sc->sc_callout, CALLOUT_MPSAFE); 99210311Sjmallett callout_reset(&sc->sc_callout, hz * 5, octeon_rnd_harvest, sc); 100210311Sjmallett 101210311Sjmallett cvmx_rng_enable(); 102210311Sjmallett 103210311Sjmallett return (0); 104210311Sjmallett} 105210311Sjmallett 106210311Sjmallettstatic int 107210311Sjmallettocteon_rnd_detach(device_t dev) 108210311Sjmallett{ 109210311Sjmallett struct octeon_rnd_softc *sc; 110210311Sjmallett 111210311Sjmallett sc = device_get_softc(dev); 112210311Sjmallett 113210311Sjmallett callout_stop(&sc->sc_callout); 114210311Sjmallett 115210311Sjmallett return (0); 116210311Sjmallett} 117210311Sjmallett 118210311Sjmallettstatic void 119210311Sjmallettocteon_rnd_harvest(void *arg) 120210311Sjmallett{ 121210311Sjmallett struct octeon_rnd_softc *sc; 122210311Sjmallett unsigned i; 123210311Sjmallett 124210311Sjmallett sc = arg; 125210311Sjmallett 126210311Sjmallett for (i = 0; i < OCTEON_RND_WORDS; i++) 127210311Sjmallett sc->sc_entropy[i] = cvmx_rng_get_random64(); 128210311Sjmallett random_harvest(sc->sc_entropy, sizeof sc->sc_entropy, 129256381Smarkm (sizeof(sc->sc_entropy)*8)/2, RANDOM_PURE_OCTEON); 130210311Sjmallett 131210311Sjmallett callout_reset(&sc->sc_callout, hz * 5, octeon_rnd_harvest, sc); 132210311Sjmallett} 133