ingenic_rng.c revision 1.4
11.4Smacallan/* $NetBSD: ingenic_rng.c,v 1.4 2016/02/17 20:12:42 macallan Exp $ */ 21.1Smacallan 31.1Smacallan/*- 41.1Smacallan * Copyright (c) 2015 Michael McConville 51.1Smacallan * All rights reserved. 61.1Smacallan * 71.1Smacallan * Redistribution and use in source and binary forms, with or without 81.1Smacallan * modification, are permitted provided that the following conditions 91.1Smacallan * are met: 101.1Smacallan * 1. Redistributions of source code must retain the above copyright 111.1Smacallan * notice, this list of conditions and the following disclaimer. 121.1Smacallan * 2. Redistributions in binary form must reproduce the above copyright 131.1Smacallan * notice, this list of conditions and the following disclaimer in the 141.1Smacallan * documentation and/or other materials provided with the distribution. 151.1Smacallan * 161.1Smacallan * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 171.1Smacallan * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 181.1Smacallan * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 191.1Smacallan * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 201.1Smacallan * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 211.1Smacallan * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 221.1Smacallan * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 231.1Smacallan * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 241.1Smacallan * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 251.1Smacallan * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 261.1Smacallan * POSSIBILITY OF SUCH DAMAGE. 271.1Smacallan */ 281.1Smacallan 291.1Smacallan#include <sys/cdefs.h> 301.4Smacallan__KERNEL_RCSID(0, "$NetBSD: ingenic_rng.c,v 1.4 2016/02/17 20:12:42 macallan Exp $"); 311.2Smacallan 321.2Smacallan/* 331.2Smacallan * adapted from Jared McNeill's amlogic_rng.c 341.2Smacallan */ 351.1Smacallan 361.1Smacallan#include <sys/param.h> 371.1Smacallan#include <sys/systm.h> 381.1Smacallan#include <sys/device.h> 391.1Smacallan#include <sys/mutex.h> 401.1Smacallan#include <sys/kernel.h> 411.1Smacallan#include <sys/mutex.h> 421.1Smacallan#include <sys/bus.h> 431.1Smacallan#include <sys/rndpool.h> 441.1Smacallan#include <sys/rndsource.h> 451.1Smacallan 461.1Smacallan#include <mips/ingenic/ingenic_var.h> 471.1Smacallan#include <mips/ingenic/ingenic_regs.h> 481.1Smacallan 491.1Smacallan#include "opt_ingenic.h" 501.1Smacallan 511.1Smacallanstruct ingenic_rng_softc; 521.1Smacallan 531.1Smacallanstatic int ingenic_rng_match(device_t, cfdata_t, void *); 541.1Smacallanstatic void ingenic_rng_attach(device_t, device_t, void *); 551.1Smacallan 561.4Smacallanstatic void ingenic_rng_get(size_t, void *); 571.1Smacallan 581.1Smacallanstruct ingenic_rng_softc { 591.1Smacallan device_t sc_dev; 601.1Smacallan bus_space_tag_t sc_bst; 611.1Smacallan bus_space_handle_t sc_bsh; 621.1Smacallan 631.4Smacallan kmutex_t sc_lock; 641.1Smacallan krndsource_t sc_rndsource; 651.1Smacallan}; 661.1Smacallan 671.1SmacallanCFATTACH_DECL_NEW(ingenic_rng, sizeof(struct ingenic_rng_softc), 681.1Smacallan ingenic_rng_match, ingenic_rng_attach, NULL, NULL); 691.1Smacallan 701.1Smacallanstatic int 711.1Smacallaningenic_rng_match(device_t parent, cfdata_t cf, void *aux) 721.1Smacallan{ 731.3Smacallan const struct apbus_attach_args *aa = aux; 741.1Smacallan 751.3Smacallan return !(strcmp(aa->aa_name, "jzrng")); 761.1Smacallan} 771.1Smacallan 781.1Smacallanstatic void 791.1Smacallaningenic_rng_attach(device_t parent, device_t self, void *aux) 801.1Smacallan{ 811.1Smacallan struct ingenic_rng_softc * const sc = device_private(self); 821.3Smacallan const struct apbus_attach_args * const aa = aux; 831.3Smacallan bus_addr_t addr = aa->aa_addr; 841.1Smacallan int error; 851.1Smacallan 861.1Smacallan sc->sc_dev = self; 871.1Smacallan sc->sc_bst = aa->aa_bst; 881.3Smacallan if (addr == 0) 891.3Smacallan addr = JZ_RNG; 901.1Smacallan 911.3Smacallan error = bus_space_map(aa->aa_bst, addr, 4, 0, &sc->sc_bsh); 921.1Smacallan if (error) { 931.1Smacallan aprint_error_dev(self, 941.3Smacallan "can't map registers for %s: %d\n", aa->aa_name, error); 951.1Smacallan return; 961.1Smacallan } 971.1Smacallan 981.4Smacallan mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_VM); 991.4Smacallan 1001.1Smacallan aprint_naive(": Ingenic random number generator\n"); 1011.1Smacallan aprint_normal(": Ingenic random number generator\n"); 1021.1Smacallan 1031.4Smacallan rndsource_setcb(&sc->sc_rndsource, ingenic_rng_get, sc); 1041.1Smacallan rnd_attach_source(&sc->sc_rndsource, device_xname(self), RND_TYPE_RNG, 1051.1Smacallan RND_FLAG_COLLECT_VALUE|RND_FLAG_HASCB); 1061.1Smacallan 1071.4Smacallan ingenic_rng_get(RND_POOLBITS / NBBY, sc); 1081.1Smacallan} 1091.1Smacallan 1101.1Smacallanstatic void 1111.4Smacallaningenic_rng_get(size_t bytes_wanted, void *priv) 1121.1Smacallan{ 1131.4Smacallan struct ingenic_rng_softc * const sc = priv; 1141.1Smacallan uint32_t data; 1151.1Smacallan 1161.4Smacallan mutex_spin_enter(&sc->sc_lock); 1171.4Smacallan while (bytes_wanted) { 1181.3Smacallan data = bus_space_read_4(sc->sc_bst, sc->sc_bsh, 0); 1191.4Smacallan delay(1); 1201.4Smacallan rnd_add_data_sync(&sc->sc_rndsource, &data, sizeof(data), 1211.1Smacallan sizeof(data) * NBBY); 1221.4Smacallan bytes_wanted -= MIN(bytes_wanted, sizeof(data)); 1231.1Smacallan } 1241.1Smacallan explicit_memset(&data, 0, sizeof(data)); 1251.4Smacallan mutex_spin_exit(&sc->sc_lock); 1261.1Smacallan} 127