Module Name:    src
Committed By:   jmcneill
Date:           Sat May 30 11:10:24 UTC 2015

Modified Files:
        src/sys/arch/arm/nvidia: tegra_car.c tegra_carreg.h

Log Message:
Use PLL LFSR as rnd source.


To generate a diff of this commit:
cvs rdiff -u -r1.19 -r1.20 src/sys/arch/arm/nvidia/tegra_car.c
cvs rdiff -u -r1.16 -r1.17 src/sys/arch/arm/nvidia/tegra_carreg.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/arm/nvidia/tegra_car.c
diff -u src/sys/arch/arm/nvidia/tegra_car.c:1.19 src/sys/arch/arm/nvidia/tegra_car.c:1.20
--- src/sys/arch/arm/nvidia/tegra_car.c:1.19	Wed May 20 00:05:53 2015
+++ src/sys/arch/arm/nvidia/tegra_car.c	Sat May 30 11:10:24 2015
@@ -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 <jmcne...@invisible.ca>
@@ -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 @@ __KERNEL_RCSID(0, "$NetBSD: tegra_car.c,
 #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 @@ struct tegra_car_softc {
 	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 @@ tegra_car_attach(device_t parent, device
 	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 @@ tegra_car_init(struct tegra_car_softc *s
 }
 
 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) {

Index: src/sys/arch/arm/nvidia/tegra_carreg.h
diff -u src/sys/arch/arm/nvidia/tegra_carreg.h:1.16 src/sys/arch/arm/nvidia/tegra_carreg.h:1.17
--- src/sys/arch/arm/nvidia/tegra_carreg.h:1.16	Mon May 18 20:36:42 2015
+++ src/sys/arch/arm/nvidia/tegra_carreg.h	Sat May 30 11:10:24 2015
@@ -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 <jmcne...@invisible.ca>
@@ -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)

Reply via email to