1280905Sganbold/*- 2280905Sganbold * Copyright 2014 John Wehle <john@feith.com> 3280905Sganbold * All rights reserved. 4280905Sganbold * 5280905Sganbold * Redistribution and use in source and binary forms, with or without 6280905Sganbold * modification, are permitted provided that the following conditions 7280905Sganbold * are met: 8280905Sganbold * 1. Redistributions of source code must retain the above copyright 9280905Sganbold * notice, this list of conditions and the following disclaimer. 10280905Sganbold * 2. Redistributions in binary form must reproduce the above copyright 11280905Sganbold * notice, this list of conditions and the following disclaimer in the 12280905Sganbold * documentation and/or other materials provided with the distribution. 13280905Sganbold * 14280905Sganbold * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15280905Sganbold * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16280905Sganbold * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17280905Sganbold * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18280905Sganbold * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19280905Sganbold * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20280905Sganbold * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21280905Sganbold * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22280905Sganbold * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23280905Sganbold * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24280905Sganbold * SUCH DAMAGE. 25280905Sganbold */ 26280905Sganbold 27280905Sganbold/* 28280905Sganbold * Amlogic aml8726 random number generator driver. 29280905Sganbold */ 30280905Sganbold 31280905Sganbold#include <sys/cdefs.h> 32280905Sganbold__FBSDID("$FreeBSD$"); 33280905Sganbold 34280905Sganbold#include <sys/param.h> 35280905Sganbold#include <sys/systm.h> 36280905Sganbold#include <sys/conf.h> 37280905Sganbold#include <sys/bus.h> 38280905Sganbold#include <sys/kernel.h> 39280905Sganbold#include <sys/module.h> 40280905Sganbold#include <sys/lock.h> 41280905Sganbold#include <sys/mutex.h> 42280905Sganbold#include <sys/resource.h> 43280905Sganbold#include <sys/rman.h> 44280905Sganbold#include <sys/random.h> 45280905Sganbold 46280905Sganbold#include <machine/bus.h> 47280905Sganbold 48280905Sganbold#include <dev/fdt/fdt_common.h> 49280905Sganbold#include <dev/ofw/ofw_bus.h> 50280905Sganbold#include <dev/ofw/ofw_bus_subr.h> 51280905Sganbold 52280905Sganbold 53280905Sganboldstruct aml8726_rng_softc { 54280905Sganbold device_t dev; 55280905Sganbold struct resource *res[1]; 56280905Sganbold struct callout co; 57280905Sganbold int ticks; 58280905Sganbold}; 59280905Sganbold 60280905Sganboldstatic struct resource_spec aml8726_rng_spec[] = { 61280905Sganbold { SYS_RES_MEMORY, 0, RF_ACTIVE }, 62280905Sganbold { -1, 0 } 63280905Sganbold}; 64280905Sganbold 65280905Sganbold#define AML_RNG_0_REG 0 66280905Sganbold#define AML_RNG_1_REG 4 67280905Sganbold 68280905Sganbold#define CSR_READ_4(sc, reg) bus_read_4((sc)->res[0], reg) 69280905Sganbold 70280905Sganboldstatic void 71280905Sganboldaml8726_rng_harvest(void *arg) 72280905Sganbold{ 73280905Sganbold struct aml8726_rng_softc *sc = arg; 74280905Sganbold uint32_t rn[2]; 75280905Sganbold 76280905Sganbold rn[0] = CSR_READ_4(sc, AML_RNG_0_REG); 77280905Sganbold rn[1] = CSR_READ_4(sc, AML_RNG_1_REG); 78280905Sganbold 79280905Sganbold random_harvest(rn, sizeof(rn), sizeof(rn) * NBBY / 2, 80280905Sganbold RANDOM_PURE_AML8726); 81280905Sganbold 82280905Sganbold callout_reset(&sc->co, sc->ticks, aml8726_rng_harvest, sc); 83280905Sganbold} 84280905Sganbold 85280905Sganboldstatic int 86280905Sganboldaml8726_rng_probe(device_t dev) 87280905Sganbold{ 88280905Sganbold 89280905Sganbold if (!ofw_bus_status_okay(dev)) 90280905Sganbold return (ENXIO); 91280905Sganbold 92280905Sganbold if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-rng")) 93280905Sganbold return (ENXIO); 94280905Sganbold 95280905Sganbold device_set_desc(dev, "Amlogic aml8726 RNG"); 96280905Sganbold 97280905Sganbold return (BUS_PROBE_DEFAULT); 98280905Sganbold} 99280905Sganbold 100280905Sganboldstatic int 101280905Sganboldaml8726_rng_attach(device_t dev) 102280905Sganbold{ 103280905Sganbold struct aml8726_rng_softc *sc = device_get_softc(dev); 104280905Sganbold 105280905Sganbold sc->dev = dev; 106280905Sganbold 107280905Sganbold if (bus_alloc_resources(dev, aml8726_rng_spec, sc->res)) { 108280905Sganbold device_printf(dev, "can not allocate resources for device\n"); 109280905Sganbold return (ENXIO); 110280905Sganbold } 111280905Sganbold 112280905Sganbold /* Install a periodic collector for the RNG */ 113280905Sganbold if (hz > 100) 114280905Sganbold sc->ticks = hz / 100; 115280905Sganbold else 116280905Sganbold sc->ticks = 1; 117280905Sganbold 118283291Sjkim callout_init(&sc->co, 1); 119280905Sganbold callout_reset(&sc->co, sc->ticks, aml8726_rng_harvest, sc); 120280905Sganbold 121280905Sganbold return (0); 122280905Sganbold} 123280905Sganbold 124280905Sganboldstatic int 125280905Sganboldaml8726_rng_detach(device_t dev) 126280905Sganbold{ 127280905Sganbold struct aml8726_rng_softc *sc = device_get_softc(dev); 128280905Sganbold 129280905Sganbold callout_drain(&sc->co); 130280905Sganbold 131280905Sganbold bus_release_resources(dev, aml8726_rng_spec, sc->res); 132280905Sganbold 133280905Sganbold return (0); 134280905Sganbold} 135280905Sganbold 136280905Sganboldstatic device_method_t aml8726_rng_methods[] = { 137280905Sganbold /* Device interface */ 138280905Sganbold DEVMETHOD(device_probe, aml8726_rng_probe), 139280905Sganbold DEVMETHOD(device_attach, aml8726_rng_attach), 140280905Sganbold DEVMETHOD(device_detach, aml8726_rng_detach), 141280905Sganbold 142280905Sganbold DEVMETHOD_END 143280905Sganbold}; 144280905Sganbold 145280905Sganboldstatic driver_t aml8726_rng_driver = { 146280905Sganbold "rng", 147280905Sganbold aml8726_rng_methods, 148280905Sganbold sizeof(struct aml8726_rng_softc), 149280905Sganbold}; 150280905Sganbold 151280905Sganboldstatic devclass_t aml8726_rng_devclass; 152280905Sganbold 153280905SganboldDRIVER_MODULE(aml8726_rng, simplebus, aml8726_rng_driver, 154280905Sganbold aml8726_rng_devclass, 0, 0); 155280905SganboldMODULE_DEPEND(aml8726_rng, random, 1, 1, 1); 156