Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F164666065
D32723.id97645.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
11 KB
Referenced Files
None
Subscribers
None
D32723.id97645.diff
View Options
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, ®, 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
Details
Attached
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)
Attached To
Mode
D32723: ipq4018: add SoC reset, SMP, reset syscon and qcom_rnd driver
Attached
Detach File
Event Timeline
Log In to Comment