Page MenuHomeFreeBSD

D48943.diff
No OneTemporary

D48943.diff

diff --git a/sys/dev/clk/starfive/jh7110_clk_stg.c b/sys/dev/clk/starfive/jh7110_clk_stg.c
--- a/sys/dev/clk/starfive/jh7110_clk_stg.c
+++ b/sys/dev/clk/starfive/jh7110_clk_stg.c
@@ -52,6 +52,9 @@
static const char *pcie0_apb_p[] = { "apb_bus" };
static const char *pcie1_apb_p[] = { "apb_bus" };
+static const char *sec_ahb_p[] = { "stg_axiahb" };
+static const char *sec_misc_ahb_p[] = { "stg_axiahb" };
+
static const char *usb0_lpm_p[] = { "osc" };
static const char *usb0_stb_p[] = { "osc" };
static const char *usb0_apb_p[] = { "apb_bus" };
@@ -86,6 +89,9 @@
JH7110_GATE(JH7110_STGCLK_PCIE_SLV_MAIN, "pcie_slv_main",
pcie_slv_main_p),
+ JH7110_GATE(JH7110_STGCLK_SEC_AHB, "sec_ahb", sec_ahb_p),
+ JH7110_GATE(JH7110_STGCLK_SEC_MISC_AHB, "sec_misc_ahb", sec_misc_ahb_p),
+
JH7110_GATEDIV(JH7110_STGCLK_E2_RTC, "e2_rtc", e2_rtc_p, 24),
JH7110_GATE(JH7110_STGCLK_E2_CORE, "e2_core", e2_core_p),
JH7110_GATE(JH7110_STGCLK_E2_DBG, "e2_dbg", e2_dbg_p),
diff --git a/sys/dev/random/random_harvestq.c b/sys/dev/random/random_harvestq.c
--- a/sys/dev/random/random_harvestq.c
+++ b/sys/dev/random/random_harvestq.c
@@ -387,6 +387,7 @@
[RANDOM_PURE_QUALCOMM] = "PURE_QUALCOMM",
[RANDOM_PURE_ARMV8] = "PURE_ARMV8",
[RANDOM_PURE_ARM_TRNG] = "PURE_ARM_TRNG",
+ [RANDOM_PURE_STARFIVE_TRNG] = "PURE_STARFIVE_TRNG",
/* "ENTROPYSOURCE" */
};
diff --git a/sys/riscv/starfive/files.starfive b/sys/riscv/starfive/files.starfive
--- a/sys/riscv/starfive/files.starfive
+++ b/sys/riscv/starfive/files.starfive
@@ -4,5 +4,6 @@
dev/clk/starfive/jh7110_clk_sys.c standard
dev/clk/starfive/jh7110_clk_stg.c standard
dev/mmc/host/dwmmc_starfive.c optional dwmmc_starfive fdt
+riscv/starfive/jh7110_trng.c optional !random_loadable fdt
riscv/starfive/starfive_syscon.c standard
diff --git a/sys/riscv/starfive/jh7110_trng.c b/sys/riscv/starfive/jh7110_trng.c
new file mode 100644
--- /dev/null
+++ b/sys/riscv/starfive/jh7110_trng.c
@@ -0,0 +1,205 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 Jari Sihvola <jsihv@gmx.com>
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/random.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <dev/clk/clk.h>
+#include <dev/hwreset/hwreset.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+/* Registers */
+#define JH7110_TRNG_CTRL 0x0000
+#define CTRL_GEN_RAND 0x1
+#define CTRL_RESEED 0x2
+#define JH7110_TRNG_STAT 0x0004
+#define STAT_SEEDING_DONE (1 << 9)
+#define JH7110_TRNG_MODE 0x000c
+#define MODE_256BIT (1 << 3)
+#define JH7110_TRNG_ISTAT 0x0014
+#define ISTAT_RAND_DONE (1 << 0)
+#define ISTAT_LFSR_LOCKUP (1 << 4)
+/* There is eight adjacent 32-bit registers for random data */
+#define JH7110_TRNG_DATA 0x0020
+#define DATA_REGS 8
+#define DATA_BYTESIZE (DATA_REGS * sizeof(uint32_t))
+
+struct jh7110_trng_softc {
+ device_t dev;
+ struct resource *mem_res;
+ struct callout trngto;
+ clk_t clk_hclk;
+ clk_t clk_ahb;
+ hwreset_t rst;
+};
+
+static struct ofw_compat_data compat_data[] = {
+ {"starfive,jh7110-trng", 1},
+ {NULL, 0}
+};
+
+#define RD4(sc, reg) bus_read_4((sc)->mem_res, (reg))
+#define WR4(sc, reg, val) bus_write_4((sc)->mem_res, (reg), (val))
+
+static int
+jh7110_trng_probe(device_t dev)
+{
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "StarFive JH7110 TRNG");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static void
+jh7110_trng_harvest(void *arg)
+{
+ struct jh7110_trng_softc *sc = arg;
+ uint32_t val, buf[DATA_REGS];
+ int i;
+
+ val = RD4(sc, JH7110_TRNG_STAT);
+ if (val & STAT_SEEDING_DONE) {
+ val = RD4(sc, JH7110_TRNG_ISTAT);
+ if (val & ISTAT_RAND_DONE) {
+ WR4(sc, JH7110_TRNG_ISTAT, ISTAT_RAND_DONE);
+
+ for (i = 0; i != DATA_REGS; i++)
+ buf[i] = RD4(sc, JH7110_TRNG_DATA +
+ i * sizeof(uint32_t));
+
+ random_harvest_queue(buf, DATA_BYTESIZE,
+ RANDOM_PURE_STARFIVE_TRNG);
+ }
+ if (val & ISTAT_LFSR_LOCKUP)
+ WR4(sc, JH7110_TRNG_CTRL, CTRL_RESEED);
+ else
+ WR4(sc, JH7110_TRNG_CTRL, CTRL_GEN_RAND);
+ }
+ callout_reset(&sc->trngto, hz, jh7110_trng_harvest, sc);
+}
+
+static int
+jh7110_trng_detach(device_t dev)
+{
+ struct jh7110_trng_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ callout_drain(&sc->trngto);
+
+ if (sc->mem_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
+
+ if (sc->clk_hclk != NULL)
+ clk_release(sc->clk_hclk);
+ if (sc->clk_ahb != NULL)
+ clk_release(sc->clk_ahb);
+
+ hwreset_release(sc->rst);
+
+ return (0);
+}
+
+static int
+jh7110_trng_attach(device_t dev)
+{
+ struct jh7110_trng_softc *sc;
+ uint32_t val;
+ int rid;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+ sc->clk_hclk = NULL;
+ sc->clk_ahb = NULL;
+
+ /* Initialize callout */
+ callout_init(&sc->trngto, CALLOUT_MPSAFE);
+
+ /* Allocate memory resources */
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ jh7110_trng_detach(dev);
+ return (ENXIO);
+ }
+
+ /* Get and enable clocks */
+ if (clk_get_by_ofw_name(dev, 0, "hclk", &sc->clk_hclk) != 0) {
+ device_printf(dev, "could not get hclk clock\n");
+ sc->clk_hclk = NULL;
+ return (ENXIO);
+ }
+ if (clk_get_by_ofw_name(dev, 0, "ahb", &sc->clk_ahb) != 0) {
+ device_printf(dev, "could not get ahb clock\n");
+ sc->clk_ahb = NULL;
+ return (ENXIO);
+ }
+ if (clk_enable(sc->clk_hclk) != 0) {
+ device_printf(dev, "could not enable hclk clock\n");
+ return (ENXIO);
+ }
+ if (clk_enable(sc->clk_ahb) != 0) {
+ device_printf(dev, "could not enable ahb clock\n");
+ return (ENXIO);
+ }
+
+ /* Get and de-assert reset */
+ if (hwreset_get_by_ofw_idx(dev, 0, 0, &sc->rst) != 0) {
+ device_printf(dev, "could not get reset\n");
+ return (ENXIO);
+ }
+ if (hwreset_deassert(sc->rst) != 0) {
+ device_printf(dev, "could not deassert reset\n");
+ return (ENXIO);
+ }
+
+ /* Clear register ISTAT */
+ val = RD4(sc, JH7110_TRNG_ISTAT);
+ WR4(sc, JH7110_TRNG_ISTAT, val);
+
+ /* Set 256 bit mode */
+ WR4(sc, JH7110_TRNG_MODE, MODE_256BIT);
+
+ /* Start harvesting */
+ WR4(sc, JH7110_TRNG_CTRL, CTRL_RESEED);
+ callout_reset(&sc->trngto, hz, jh7110_trng_harvest, sc);
+ jh7110_trng_harvest(sc);
+
+ return (0);
+}
+
+static device_method_t jh7110_trng_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, jh7110_trng_probe),
+ DEVMETHOD(device_attach, jh7110_trng_attach),
+ DEVMETHOD(device_detach, jh7110_trng_detach),
+
+ DEVMETHOD_END
+};
+
+static driver_t jh7110_trng_driver = {
+ "jh7110trng",
+ jh7110_trng_methods,
+ sizeof(struct jh7110_trng_softc)
+};
+
+DRIVER_MODULE(jh7110_trng, simplebus, jh7110_trng_driver, 0, 0);
+MODULE_VERSION(jh7110_trng, 1);
+MODULE_DEPEND(jh7110_trng, randomdev, 1, 1, 1);
diff --git a/sys/sys/random.h b/sys/sys/random.h
--- a/sys/sys/random.h
+++ b/sys/sys/random.h
@@ -104,6 +104,7 @@
RANDOM_PURE_QUALCOMM,
RANDOM_PURE_ARMV8,
RANDOM_PURE_ARM_TRNG,
+ RANDOM_PURE_STARFIVE_TRNG,
ENTROPYSOURCE
};
_Static_assert(ENTROPYSOURCE <= 32,

File Metadata

Mime Type
text/plain
Expires
Sat, Apr 4, 5:56 AM (12 m, 30 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30802410
Default Alt Text
D48943.diff (7 KB)

Event Timeline