11.7Sriastrad/* $NetBSD: ingenic_rng.c,v 1.7 2022/03/19 11:55:03 riastradh 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.7Sriastrad__KERNEL_RCSID(0, "$NetBSD: ingenic_rng.c,v 1.7 2022/03/19 11:55:03 riastradh 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/rndsource.h> 441.1Smacallan 451.1Smacallan#include <mips/ingenic/ingenic_var.h> 461.1Smacallan#include <mips/ingenic/ingenic_regs.h> 471.1Smacallan 481.1Smacallan#include "opt_ingenic.h" 491.1Smacallan 501.1Smacallanstruct ingenic_rng_softc; 511.1Smacallan 521.1Smacallanstatic int ingenic_rng_match(device_t, cfdata_t, void *); 531.1Smacallanstatic void ingenic_rng_attach(device_t, device_t, void *); 541.1Smacallan 551.4Smacallanstatic void ingenic_rng_get(size_t, void *); 561.1Smacallan 571.1Smacallanstruct ingenic_rng_softc { 581.1Smacallan device_t sc_dev; 591.1Smacallan bus_space_tag_t sc_bst; 601.1Smacallan bus_space_handle_t sc_bsh; 611.1Smacallan 621.1Smacallan krndsource_t sc_rndsource; 631.1Smacallan}; 641.1Smacallan 651.1SmacallanCFATTACH_DECL_NEW(ingenic_rng, sizeof(struct ingenic_rng_softc), 661.1Smacallan ingenic_rng_match, ingenic_rng_attach, NULL, NULL); 671.1Smacallan 681.1Smacallanstatic int 691.1Smacallaningenic_rng_match(device_t parent, cfdata_t cf, void *aux) 701.1Smacallan{ 711.3Smacallan const struct apbus_attach_args *aa = aux; 721.1Smacallan 731.3Smacallan return !(strcmp(aa->aa_name, "jzrng")); 741.1Smacallan} 751.1Smacallan 761.1Smacallanstatic void 771.1Smacallaningenic_rng_attach(device_t parent, device_t self, void *aux) 781.1Smacallan{ 791.1Smacallan struct ingenic_rng_softc * const sc = device_private(self); 801.3Smacallan const struct apbus_attach_args * const aa = aux; 811.3Smacallan bus_addr_t addr = aa->aa_addr; 821.1Smacallan int error; 831.1Smacallan 841.1Smacallan sc->sc_dev = self; 851.1Smacallan sc->sc_bst = aa->aa_bst; 861.3Smacallan if (addr == 0) 871.3Smacallan addr = JZ_RNG; 881.1Smacallan 891.3Smacallan error = bus_space_map(aa->aa_bst, addr, 4, 0, &sc->sc_bsh); 901.1Smacallan if (error) { 911.1Smacallan aprint_error_dev(self, 921.3Smacallan "can't map registers for %s: %d\n", aa->aa_name, error); 931.1Smacallan return; 941.1Smacallan } 951.1Smacallan 961.1Smacallan aprint_naive(": Ingenic random number generator\n"); 971.1Smacallan aprint_normal(": Ingenic random number generator\n"); 981.1Smacallan 991.4Smacallan rndsource_setcb(&sc->sc_rndsource, ingenic_rng_get, sc); 1001.1Smacallan rnd_attach_source(&sc->sc_rndsource, device_xname(self), RND_TYPE_RNG, 1011.1Smacallan RND_FLAG_COLLECT_VALUE|RND_FLAG_HASCB); 1021.1Smacallan} 1031.1Smacallan 1041.1Smacallanstatic void 1051.4Smacallaningenic_rng_get(size_t bytes_wanted, void *priv) 1061.1Smacallan{ 1071.4Smacallan struct ingenic_rng_softc * const sc = priv; 1081.1Smacallan uint32_t data; 1091.1Smacallan 1101.4Smacallan while (bytes_wanted) { 1111.3Smacallan data = bus_space_read_4(sc->sc_bst, sc->sc_bsh, 0); 1121.4Smacallan delay(1); 1131.4Smacallan rnd_add_data_sync(&sc->sc_rndsource, &data, sizeof(data), 1141.1Smacallan sizeof(data) * NBBY); 1151.4Smacallan bytes_wanted -= MIN(bytes_wanted, sizeof(data)); 1161.1Smacallan } 1171.1Smacallan explicit_memset(&data, 0, sizeof(data)); 1181.1Smacallan} 119