Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F152063074
D37882.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D37882.diff
View Options
diff --git a/sys/arm64/conf/std.qcom b/sys/arm64/conf/std.qcom
--- a/sys/arm64/conf/std.qcom
+++ b/sys/arm64/conf/std.qcom
@@ -4,6 +4,8 @@
# Qualcomm Snapdragon drivers
device qcom_gcc # Global Clock Controller
+device qcom_rng # Pseudo Random Number Generator
+device qcom_mdio # MDIO support
# Serial (COM) ports
device uart_msm # Qualcomm MSM UART driver
diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64
--- a/sys/conf/files.arm64
+++ b/sys/conf/files.arm64
@@ -618,6 +618,8 @@
# Qualcomm
arm64/qualcomm/qcom_gcc.c optional qcom_gcc fdt
+dev/qcom_rnd/qcom_rnd.c optional qcom_rng fdt
+dev/qcom_mdio/qcom_mdio_ipq4018.c optional qcom_mdio fdt mdio mii
# RockChip Drivers
arm64/rockchip/rk3328_codec.c optional fdt rk3328codec soc_rockchip_rk3328
diff --git a/sys/dev/qcom_mdio/qcom_mdio_ipq4018.c b/sys/dev/qcom_mdio/qcom_mdio_ipq4018.c
--- a/sys/dev/qcom_mdio/qcom_mdio_ipq4018.c
+++ b/sys/dev/qcom_mdio/qcom_mdio_ipq4018.c
@@ -273,6 +273,9 @@
DEVMETHOD(device_attach, qcom_mdio_ipq4018_attach),
DEVMETHOD(device_detach, qcom_mdio_ipq4018_detach),
+ /* Bus interface */
+ DEVMETHOD(bus_add_child, bus_generic_add_child),
+
/* MDIO interface */
DEVMETHOD(mdio_readreg, qcom_mdio_ipq4018_readreg),
DEVMETHOD(mdio_writereg, qcom_mdio_ipq4018_writereg),
diff --git a/sys/dev/qcom_rnd/qcom_rnd.c b/sys/dev/qcom_rnd/qcom_rnd.c
--- a/sys/dev/qcom_rnd/qcom_rnd.c
+++ b/sys/dev/qcom_rnd/qcom_rnd.c
@@ -2,6 +2,7 @@
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2021, Adrian Chadd <adrian@FreeBSD.org>
+ * Copyright (c) 2022, Bjoern A. Zeeb
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -32,15 +33,14 @@
#include <sys/param.h>
#include <sys/kernel.h>
-#include <sys/malloc.h>
#include <sys/module.h>
-#include <sys/sglist.h>
+#include <sys/bus.h>
#include <sys/random.h>
+#include <sys/rman.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>
@@ -49,64 +49,96 @@
#include <dev/random/randomdev.h>
#include <dev/random/random_harvestq.h>
-#include <dev/qcom_rnd/qcom_rnd_reg.h>
+#include "qcom_rnd_reg.h"
struct qcom_rnd_softc {
- device_t dev;
+ 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 int
-qcom_rnd_modevent(module_t mod, int type, void *unused)
+qcom_rnd_harvest(struct qcom_rnd_softc *sc, void *buf, size_t *sz)
{
- int error;
+ /*
+ * 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;
- switch (type) {
- case MOD_LOAD:
- case MOD_QUIESCE:
- case MOD_UNLOAD:
- case MOD_SHUTDOWN:
- error = 0;
- break;
- default:
- error = EOPNOTSUPP;
- break;
+ while (rz < *sz) {
+ bus_barrier(sc->reg, 0, rman_get_size(sc->reg),
+ 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);
}
- return (error);
+ 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);
}
+static struct random_source random_qcom_rnd = {
+ .rs_ident = "Qualcomm Entropy Adapter",
+ .rs_source = RANDOM_PURE_QUALCOMM,
+ .rs_read = qcom_rnd_read,
+};
+
+static const struct ofw_compat_data qcom_prng_compat_data[] = {
+ {"qcom,prng", (uintptr_t)"Qualcomm PRNG"},
+#ifdef __notyet__
+ {"qcom,prng-ee", (uintptr_t)"Qualcomm PRNG-EE"},
+#endif
+ { NULL, 0 }
+};
+
static int
qcom_rnd_probe(device_t dev)
{
- if (! ofw_bus_status_okay(dev)) {
- return (ENXIO);
- }
+ const struct ofw_compat_data *compat;
- if (ofw_bus_is_compatible(dev, "qcom,prng") == 0) {
+ if (!ofw_bus_status_okay(dev))
return (ENXIO);
+
+ compat = ofw_bus_search_compatible(dev, qcom_prng_compat_data);
+ if (compat->ocd_str != NULL) {
+ device_set_desc(dev, (const char *)compat->ocd_data);
+ return (BUS_PROBE_DEFAULT);
}
- return (0);
+ return (ENXIO);
}
static int
@@ -116,54 +148,50 @@
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)) {
+ 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);
+ sc->reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->reg_rid,
+ RF_SHAREABLE | RF_ACTIVE);
if (sc->reg == NULL) {
- device_printf(dev, "Couldn't allocate memory resource!\n");
+ device_printf(dev, "Failed to 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);
+ return (0);
+ /* Check to see whether the PRNG is already setup. */
+ /* XXX this is still racy? */
+ bus_barrier(sc->reg, 0, rman_get_size(sc->reg), 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.
- */
+/* XXX-BZ this panics */
+ if ((reg & QCOM_RND_PRNG_CONFIG_HW_ENABLE) == 0) {
+
+ /* 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);
+ bus_barrier(sc->reg, 0, rman_get_size(sc->reg),
+ 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);
+ bus_barrier(sc->reg, 0, rman_get_size(sc->reg),
+ BUS_SPACE_BARRIER_WRITE);
+ } else {
+ device_printf(dev, "PRNG HW already enabled\n");
+ /* XXX we should clear up and error? */
}
random_source_register(&random_qcom_rnd);
- return (0);
+ return (0);
}
static int
@@ -177,62 +205,15 @@
("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;
+ if (sc->reg != NULL)
+ bus_release_resource(sc->dev, SYS_RES_MEMORY, sc->reg_rid, sc->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);
- }
+ atomic_store_explicit(&g_qcom_rnd_softc, NULL, memory_order_release);
- 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);
-}
-
static device_method_t qcom_rnd_methods[] = {
/* Device methods. */
DEVMETHOD(device_probe, qcom_rnd_probe),
@@ -248,9 +229,7 @@
sizeof(struct qcom_rnd_softc)
};
-DRIVER_MODULE(qcom_rnd_random, simplebus, qcom_rnd_driver,
- qcom_rnd_modevent, 0);
-DRIVER_MODULE(qcom_rnd_random, ofwbus, qcom_rnd_driver,
- qcom_rnd_modevent, 0);
+DRIVER_MODULE(qcom_rnd_random, simplebus, qcom_rnd_driver, NULL, NULL);
+DRIVER_MODULE(qcom_rnd_random, ofwbus, qcom_rnd_driver, NULL, NULL);
MODULE_DEPEND(qcom_rnd_random, random_device, 1, 1, 1);
MODULE_VERSION(qcom_rnd_random, 1);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Apr 13, 11:18 AM (9 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31407798
Default Alt Text
D37882.diff (9 KB)
Attached To
Mode
D37882: QCOM: various bits
Attached
Detach File
Event Timeline
Log In to Comment