Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/arm/nvidia Use PLL LFSR as rnd source.



details:   https://anonhg.NetBSD.org/src/rev/48c2a9565f4e
branches:  trunk
changeset: 808698:48c2a9565f4e
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Sat May 30 11:10:24 2015 +0000

description:
Use PLL LFSR as rnd source.

diffstat:

 sys/arch/arm/nvidia/tegra_car.c    |  79 +++++++++++++++++++++++++++++++++++++-
 sys/arch/arm/nvidia/tegra_carreg.h |   5 +-
 2 files changed, 81 insertions(+), 3 deletions(-)

diffs (143 lines):

diff -r df701e959a62 -r 48c2a9565f4e sys/arch/arm/nvidia/tegra_car.c
--- a/sys/arch/arm/nvidia/tegra_car.c   Sat May 30 06:41:08 2015 +0000
+++ b/sys/arch/arm/nvidia/tegra_car.c   Sat May 30 11:10:24 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_car.c,v 1.19 2015/05/20 00:05:53 jmcneill Exp $ */
+/* $NetBSD: tegra_car.c,v 1.20 2015/05/30 11:10:24 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -29,7 +29,7 @@
 #include "locators.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tegra_car.c,v 1.19 2015/05/20 00:05:53 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tegra_car.c,v 1.20 2015/05/30 11:10:24 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -37,6 +37,8 @@
 #include <sys/intr.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
+#include <sys/rndpool.h>
+#include <sys/rndsource.h>
 
 #include <arm/nvidia/tegra_reg.h>
 #include <arm/nvidia/tegra_carreg.h>
@@ -50,9 +52,18 @@
        device_t                sc_dev;
        bus_space_tag_t         sc_bst;
        bus_space_handle_t      sc_bsh;
+
+       kmutex_t                sc_intr_lock;
+       kmutex_t                sc_rnd_lock;
+       u_int                   sc_bytes_wanted;
+       void                    *sc_sih;
+       krndsource_t            sc_rndsource;
 };
 
 static void    tegra_car_init(struct tegra_car_softc *);
+static void    tegra_car_rnd_attach(device_t);
+static void    tegra_car_rnd_intr(void *);
+static void    tegra_car_rnd_callback(size_t, void *);
 
 static struct tegra_car_softc *pmc_softc = NULL;
 
@@ -91,6 +102,8 @@
        aprint_verbose_dev(self, "PLLU = %u Hz\n", tegra_car_pllu_rate());
        aprint_verbose_dev(self, "PLLP0 = %u Hz\n", tegra_car_pllp0_rate());
        aprint_verbose_dev(self, "PLLD2 = %u Hz\n", tegra_car_plld2_rate());
+
+       config_interrupts(self, tegra_car_rnd_attach);
 }
 
 static void
@@ -108,6 +121,68 @@
 }
 
 static void
+tegra_car_rnd_attach(device_t self)
+{
+       struct tegra_car_softc * const sc = device_private(self);
+
+       mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SERIAL);
+       mutex_init(&sc->sc_rnd_lock, MUTEX_DEFAULT, IPL_SERIAL);
+       sc->sc_bytes_wanted = 0;
+       sc->sc_sih = softint_establish(SOFTINT_SERIAL|SOFTINT_MPSAFE,
+           tegra_car_rnd_intr, sc);
+       if (sc->sc_sih == NULL) {
+               aprint_error_dev(sc->sc_dev, "couldn't establish softint\n");
+               return;
+       }
+
+       rndsource_setcb(&sc->sc_rndsource, tegra_car_rnd_callback, sc);
+       rnd_attach_source(&sc->sc_rndsource, device_xname(sc->sc_dev),
+           RND_TYPE_RNG, RND_FLAG_COLLECT_VALUE|RND_FLAG_HASCB);
+}
+
+static void
+tegra_car_rnd_intr(void *priv)
+{
+       struct tegra_car_softc * const sc = priv;
+       uint16_t buf[512];
+       uint32_t cnt;
+
+       mutex_enter(&sc->sc_intr_lock);
+       while (sc->sc_bytes_wanted) {
+               const u_int nbytes = MIN(sc->sc_bytes_wanted, 1024);
+               for (cnt = 0; cnt < sc->sc_bytes_wanted / 2; cnt++) {
+                       buf[cnt] = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
+                           CAR_PLL_LFSR_REG) & 0xffff;
+               }
+               mutex_exit(&sc->sc_intr_lock);
+               mutex_enter(&sc->sc_rnd_lock);
+               rnd_add_data(&sc->sc_rndsource, buf, nbytes, nbytes * NBBY);
+               mutex_exit(&sc->sc_rnd_lock);
+               mutex_enter(&sc->sc_intr_lock);
+               sc->sc_bytes_wanted -= MIN(sc->sc_bytes_wanted, nbytes);
+       }
+       explicit_memset(buf, 0, sizeof(buf));
+       mutex_exit(&sc->sc_intr_lock);
+}
+
+static void
+tegra_car_rnd_callback(size_t bytes_wanted, void *priv)
+{
+       struct tegra_car_softc * const sc = priv;
+
+       mutex_enter(&sc->sc_intr_lock);
+       if (sc->sc_bytes_wanted == 0) {
+               softint_schedule(sc->sc_sih);
+       }
+       if (bytes_wanted > (UINT_MAX - sc->sc_bytes_wanted)) {
+               sc->sc_bytes_wanted = UINT_MAX;
+       } else {
+               sc->sc_bytes_wanted += bytes_wanted;
+       }
+       mutex_exit(&sc->sc_intr_lock);
+}
+
+static void
 tegra_car_get_bs(bus_space_tag_t *pbst, bus_space_handle_t *pbsh)
 {
        if (pmc_softc) {
diff -r df701e959a62 -r 48c2a9565f4e sys/arch/arm/nvidia/tegra_carreg.h
--- a/sys/arch/arm/nvidia/tegra_carreg.h        Sat May 30 06:41:08 2015 +0000
+++ b/sys/arch/arm/nvidia/tegra_carreg.h        Sat May 30 11:10:24 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_carreg.h,v 1.16 2015/05/18 20:36:42 jmcneill Exp $ */
+/* $NetBSD: tegra_carreg.h,v 1.17 2015/05/30 11:10:24 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -33,6 +33,9 @@
 #define CAR_CLK_OUT_ENB_H_REG  0x14
 #define CAR_CLK_OUT_ENB_U_REG  0x18
 
+#define CAR_PLL_LFSR_REG       0x54
+#define CAR_PLL_LFSR_RND               __BITS(15,0)
+
 #define CAR_PLLP_BASE_REG      0xa0
 #define CAR_PLLP_BASE_BYPASS           __BIT(31)
 #define CAR_PLLP_BASE_ENABLE           __BIT(30)



Home | Main Index | Thread Index | Old Index