Page MenuHomeFreeBSD

D32723.id97645.diff
No OneTemporary

D32723.id97645.diff

Index: sys/arm/conf/std.qca
===================================================================
--- sys/arm/conf/std.qca
+++ sys/arm/conf/std.qca
@@ -12,6 +12,9 @@
device uart
device uart_msm # Qualcomm MSM UART driver
+# Random
+device qcom_rnd
+
device gic
# MMC/SD/SDIO Card slot support
Index: sys/arm/qualcomm/ipq4018_machdep.c
===================================================================
--- sys/arm/qualcomm/ipq4018_machdep.c
+++ sys/arm/qualcomm/ipq4018_machdep.c
@@ -36,10 +36,12 @@
#include <sys/reboot.h>
#include <sys/devmap.h>
#include <sys/physmem.h>
+#include <sys/lock.h>
#include <vm/vm.h>
#include <machine/bus.h>
+#include <machine/fdt.h>
#include <machine/intr.h>
#include <machine/machdep.h>
#include <machine/platformvar.h>
@@ -94,12 +96,52 @@
* a call to pmap_mapdev() when the bus space code is doing its thing.
*/
devmap_add_entry(IPQ4018_MEM_UART1_START, IPQ4018_MEM_UART1_SIZE);
+
+ /*
+ * This covers a bunch of the reset block, which includes the PS-HOLD
+ * register for dropping power.
+ */
+ devmap_add_entry(IPQ4018_MEM_PSHOLD_START, IPQ4018_MEM_PSHOLD_SIZE);
+
return (0);
}
+/*
+ * This toggles the PS-HOLD register which on most IPQ devices will toggle
+ * the power control block and reset the SoC.
+ *
+ * However, there are apparently some units out there where this is not
+ * appropriate and instead the watchdog needs to be used.
+ *
+ * For now since there's only going to be one or two initial supported boards
+ * this will be fine. But if this doesn't reboot cleanly, now you know.
+ */
+static void
+ipq4018_cpu_reset_pshold(void)
+{
+ bus_space_handle_t pshold;
+
+ printf("%s: called\n", __func__);
+
+ bus_space_map(fdtbus_bs_tag, IPQ4018_MEM_PSHOLD_START,
+ IPQ4018_MEM_PSHOLD_SIZE, 0, &pshold);
+ bus_space_write_4(fdtbus_bs_tag, pshold, 0, 0);
+ bus_space_barrier(fdtbus_bs_tag, pshold, 0, 0x4,
+ BUS_SPACE_BARRIER_WRITE);
+}
+
static void
ipq4018_cpu_reset(platform_t plat)
{
+ spinlock_enter();
+ dsb();
+
+ ipq4018_cpu_reset_pshold();
+
+ /* Spin */
+ printf("%s: spinning\n", __func__);
+ while(1)
+ ;
}
/*
Index: sys/arm/qualcomm/ipq4018_reg.h
===================================================================
--- sys/arm/qualcomm/ipq4018_reg.h
+++ sys/arm/qualcomm/ipq4018_reg.h
@@ -39,4 +39,7 @@
#define IPQ4018_MEM_UART1_START 0x078af000
#define IPQ4018_MEM_UART1_SIZE 0x00001000
+#define IPQ4018_MEM_PSHOLD_START 0x004ab000
+#define IPQ4018_MEM_PSHOLD_SIZE 0x00001000
+
#endif
Index: sys/arm/qualcomm/std.ipq4018
===================================================================
--- sys/arm/qualcomm/std.ipq4018
+++ sys/arm/qualcomm/std.ipq4018
@@ -1,2 +1,4 @@
arm/qualcomm/ipq4018_machdep.c standard
arm/qualcomm/ipq4018_mp.c optional smp
+
+dev/qcom_rnd/qcom_rnd.c optional qcom_rnd
Index: sys/dev/qcom_rnd/qcom_rnd.c
===================================================================
--- /dev/null
+++ sys/dev/qcom_rnd/qcom_rnd.c
@@ -0,0 +1,259 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2021, Adrian Chadd <adrian@FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Driver for Qualcomm MSM entropy device. */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/sglist.h>
+#include <sys/random.h>
+#include <sys/stdatomic.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/bus.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/random/randomdev.h>
+#include <dev/random/random_harvestq.h>
+
+#include <dev/qcom_rnd/qcom_rnd_reg.h>
+
+struct qcom_rnd_softc {
+ device_t dev;
+ int reg_rid;
+ struct resource *reg;
+};
+
+static int qcom_rnd_modevent(module_t, int, void *);
+
+static int qcom_rnd_probe(device_t);
+static int qcom_rnd_attach(device_t);
+static int qcom_rnd_detach(device_t);
+
+static int qcom_rnd_harvest(struct qcom_rnd_softc *, void *, size_t *);
+static unsigned qcom_rnd_read(void *, unsigned);
+
+static struct random_source random_qcom_rnd = {
+ .rs_ident = "Qualcomm Entropy Adapter",
+ .rs_source = RANDOM_PURE_QUALCOMM,
+ .rs_read = qcom_rnd_read,
+};
+
+/* Kludge for API limitations of random(4). */
+static _Atomic(struct qcom_rnd_softc *) g_qcom_rnd_softc;
+
+static device_method_t qcom_rnd_methods[] = {
+ /* Device methods. */
+ DEVMETHOD(device_probe, qcom_rnd_probe),
+ DEVMETHOD(device_attach, qcom_rnd_attach),
+ DEVMETHOD(device_detach, qcom_rnd_detach),
+
+ DEVMETHOD_END
+};
+
+static driver_t qcom_rnd_driver = {
+ "qcom_rnd",
+ qcom_rnd_methods,
+ sizeof(struct qcom_rnd_softc)
+};
+static devclass_t qcom_rnd_devclass;
+
+MODULE_VERSION(qcom_rnd_random, 1);
+
+DRIVER_MODULE(qcom_rnd_random, simplebus, qcom_rnd_driver, qcom_rnd_devclass, 0, 0);
+DRIVER_MODULE(qcom_rnd_random, ofwbus, qcom_rnd_driver, qcom_rnd_devclass, 0, 0);
+// TODO: dependencies!
+//MODULE_DEPEND(qcom_rnd_random, random_device, 1, 1, 1);
+
+/* TODO: module stuff for load/unload! */
+
+static int
+qcom_rnd_modevent(module_t mod, int type, void *unused)
+{
+ int error;
+
+ switch (type) {
+ case MOD_LOAD:
+ case MOD_QUIESCE:
+ case MOD_UNLOAD:
+ case MOD_SHUTDOWN:
+ error = 0;
+ break;
+ default:
+ error = EOPNOTSUPP;
+ break;
+ }
+
+ return (error);
+}
+
+static int
+qcom_rnd_probe(device_t dev)
+{
+ if (! ofw_bus_status_okay(dev)) {
+ return (ENXIO);
+ }
+
+ if (ofw_bus_is_compatible(dev, "qcom,prng") == 0) {
+ return (ENXIO);
+ }
+
+ return (0);
+}
+
+static int
+qcom_rnd_attach(device_t dev)
+{
+ struct qcom_rnd_softc *sc, *exp;
+ uint32_t reg;
+
+ sc = device_get_softc(dev);
+
+
+ /* Found a compatible device! */
+
+ sc->dev = dev;
+
+ exp = NULL;
+ if (!atomic_compare_exchange_strong_explicit(&g_qcom_rnd_softc, &exp,
+ sc, memory_order_release, memory_order_acquire)) {
+ return (ENXIO);
+ }
+
+ sc->reg_rid = 0;
+ sc->reg = bus_alloc_resource_anywhere(dev, SYS_RES_MEMORY,
+ &sc->reg_rid, 0x140, RF_ACTIVE);
+ if (sc->reg == NULL) {
+ device_printf(dev, "Couldn't allocate memory resource!\n");
+ return (ENXIO);
+ }
+
+ device_set_desc(dev, "Qualcomm PRNG");
+
+ /*
+ * Check to see whether the PRNG has already been setup or not.
+ */
+ bus_barrier(sc->reg, 0, 0x120, BUS_SPACE_BARRIER_READ);
+ reg = bus_read_4(sc->reg, QCOM_RND_PRNG_CONFIG);
+ if (reg & QCOM_RND_PRNG_CONFIG_HW_ENABLE) {
+ device_printf(dev, "PRNG HW already enabled\n");
+ } else {
+ /*
+ * Do PRNG setup and then enable it.
+ */
+ reg = bus_read_4(sc->reg, QCOM_RND_PRNG_LFSR_CFG);
+ reg &= QCOM_RND_PRNG_LFSR_CFG_MASK;
+ reg |= QCOM_RND_PRNG_LFSR_CFG_CLOCKS;
+ bus_write_4(sc->reg, QCOM_RND_PRNG_LFSR_CFG, reg);
+ bus_barrier(sc->reg, 0, 0x120, BUS_SPACE_BARRIER_WRITE);
+
+ reg = bus_read_4(sc->reg, QCOM_RND_PRNG_CONFIG);
+ reg |= QCOM_RND_PRNG_CONFIG_HW_ENABLE;
+ bus_write_4(sc->reg, QCOM_RND_PRNG_CONFIG, reg);
+ bus_barrier(sc->reg, 0, 0x120, BUS_SPACE_BARRIER_WRITE);
+ }
+
+ random_source_register(&random_qcom_rnd);
+ return (0);
+
+}
+
+static int
+qcom_rnd_detach(device_t dev)
+{
+ struct qcom_rnd_softc *sc;
+
+ sc = device_get_softc(dev);
+ KASSERT(
+ atomic_load_explicit(&g_qcom_rnd_softc, memory_order_acquire) == sc,
+ ("only one global instance at a time"));
+
+ random_source_deregister(&random_qcom_rnd);
+ if (sc->reg != NULL) {
+ bus_release_resource(sc->dev, SYS_RES_MEMORY, sc->reg_rid, sc->reg);
+ }
+ atomic_store_explicit(&g_qcom_rnd_softc, NULL, memory_order_release);
+ return (0);
+}
+
+static int
+qcom_rnd_harvest(struct qcom_rnd_softc *sc, void *buf, size_t *sz)
+{
+ /*
+ * Add data to buf until we either run out of entropy or we
+ * fill the buffer.
+ *
+ * Note - be mindful of the provided buffer size; we're reading
+ * 4 bytes at a time but we only want to supply up to the max
+ * buffer size, so don't write past it!
+ */
+ size_t rz = 0;
+ uint32_t reg;
+
+ while (rz < *sz) {
+ bus_barrier(sc->reg, 0, 0x120, BUS_SPACE_BARRIER_READ);
+ reg = bus_read_4(sc->reg, QCOM_RND_PRNG_STATUS);
+ if ((reg & QCOM_RND_PRNG_STATUS_DATA_AVAIL) == 0)
+ break;
+ reg = bus_read_4(sc->reg, QCOM_RND_PRNG_DATA_OUT);
+ memcpy(((char *) buf) + rz, &reg, sizeof(uint32_t));
+ rz += sizeof(uint32_t);
+ }
+
+ if (rz == 0)
+ return (EAGAIN);
+ *sz = rz;
+ return (0);
+}
+
+static unsigned
+qcom_rnd_read(void *buf, unsigned usz)
+{
+ struct qcom_rnd_softc *sc;
+ size_t sz;
+ int error;
+
+ sc = g_qcom_rnd_softc;
+ if (sc == NULL)
+ return (0);
+
+ sz = usz;
+ error = qcom_rnd_harvest(sc, buf, &sz);
+ if (error != 0)
+ return (0);
+
+ return (sz);
+}
Index: sys/dev/qcom_rnd/qcom_rnd_reg.h
===================================================================
--- /dev/null
+++ sys/dev/qcom_rnd/qcom_rnd_reg.h
@@ -0,0 +1,43 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2021, Adrian Chadd <adrian@FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __QCOM_RND_REG_H__
+#define __QCOM_RND_REG_H__
+
+#define QCOM_RND_PRNG_DATA_OUT 0x0000
+
+#define QCOM_RND_PRNG_STATUS 0x0004
+#define QCOM_RND_PRNG_STATUS_DATA_AVAIL (1 << 0)
+
+#define QCOM_RND_PRNG_LFSR_CFG 0x0100
+#define QCOM_RND_PRNG_LFSR_CFG_MASK 0x0000ffff
+#define QCOM_RND_PRNG_LFSR_CFG_CLOCKS 0x0000dddd
+
+#define QCOM_RND_PRNG_CONFIG 0x0104
+#define QCOM_RND_PRNG_CONFIG_HW_ENABLE (1 << 1)
+
+#endif /* __QCOM_RND_REG_H__ */
Index: sys/sys/random.h
===================================================================
--- sys/sys/random.h
+++ sys/sys/random.h
@@ -102,6 +102,7 @@
RANDOM_PURE_DARN,
RANDOM_PURE_TPM,
RANDOM_PURE_VMGENID,
+ RANDOM_PURE_QUALCOMM,
ENTROPYSOURCE
};
_Static_assert(ENTROPYSOURCE <= 32,

File Metadata

Mime Type
text/plain
Expires
Tue, Aug 4, 1:46 AM (17 m, 27 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35924359
Default Alt Text
D32723.id97645.diff (11 KB)

Event Timeline