summaryrefslogtreecommitdiff
path: root/drivers/misc
diff options
context:
space:
mode:
authorAsherah Connor <ashe@kivikakk.ee>2021-03-19 18:21:41 +1100
committerTom Rini <trini@konsulko.com>2021-04-12 17:45:39 -0400
commit69512551aa8453b8ea9d1c5c896de9b3ad9cbfdf (patch)
tree9d19e433e15c29965cf26316baac4a72531adb1d /drivers/misc
parent5b0b43e0e25dbeed62a2155e7f3be562b9ceb9bd (diff)
test: qemu: add qfw sandbox driver, dm tests, qemu tests
A sandbox driver and test are added for the qfw uclass, and a test in QEMU added for qfw functionality to confirm it doesn't break in real world use. Signed-off-by: Asherah Connor <ashe@kivikakk.ee> Reviewed-by: Simon Glass <sjg@chromium.org> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/qfw_sandbox.c127
2 files changed, 128 insertions, 0 deletions
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 53bff72428..2864b84af9 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -58,6 +58,7 @@ obj-$(CONFIG_$(SPL_)PWRSEQ) += pwrseq-uclass.o
ifdef CONFIG_QFW
obj-y += qfw.o
obj-$(CONFIG_QFW_PIO) += qfw_pio.o
+obj-$(CONFIG_SANDBOX) += qfw_sandbox.o
endif
obj-$(CONFIG_ROCKCHIP_EFUSE) += rockchip-efuse.o
obj-$(CONFIG_ROCKCHIP_OTP) += rockchip-otp.o
diff --git a/drivers/misc/qfw_sandbox.c b/drivers/misc/qfw_sandbox.c
new file mode 100644
index 0000000000..b09974d33b
--- /dev/null
+++ b/drivers/misc/qfw_sandbox.c
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Sandbox interface for QFW
+ *
+ * (C) Copyright 2015 Miao Yan <yanmiaobest@gmail.com>
+ * (C) Copyright 2021 Asherah Connor <ashe@kivikakk.ee>
+ */
+
+#define LOG_CATEGORY UCLASS_QFW
+
+#include <asm/types.h>
+#include <asm/io.h>
+#include <dm.h>
+#include <dm/device.h>
+#include <qfw.h>
+
+struct qfw_sandbox_plat {
+ u8 file_dir_offset;
+};
+
+static void qfw_sandbox_read_entry_io(struct udevice *dev, u16 entry, u32 size,
+ void *address)
+{
+ debug("%s: entry 0x%x size %u address %p\n", __func__, entry, size,
+ address);
+
+ switch (entry) {
+ case FW_CFG_SIGNATURE:
+ if (size == 4)
+ *((u32 *)address) = cpu_to_be32(QEMU_FW_CFG_SIGNATURE);
+ break;
+ case FW_CFG_ID:
+ /* Advertise DMA support */
+ if (size == 1)
+ *((u8 *)address) = FW_CFG_DMA_ENABLED;
+ break;
+ default:
+ debug("%s got unsupported entry 0x%x\n", __func__, entry);
+ /*
+ * Sandbox driver doesn't support other entries here, assume we use DMA
+ * to read them -- the uclass driver will exclusively use it when
+ * advertised.
+ */
+ }
+}
+
+static void qfw_sandbox_read_entry_dma(struct udevice *dev, struct qfw_dma *dma)
+{
+ u16 entry;
+ u32 control = be32_to_cpu(dma->control);
+ void *address = (void *)be64_to_cpu(dma->address);
+ u32 length = be32_to_cpu(dma->length);
+ struct qfw_sandbox_plat *plat = dev_get_plat(dev);
+ struct fw_cfg_file *file;
+
+ debug("%s\n", __func__);
+
+ if (!(control & FW_CFG_DMA_READ))
+ return;
+
+ if (control & FW_CFG_DMA_SELECT) {
+ /* Start new read. */
+ entry = control >> 16;
+
+ /* Arbitrary values to be used by tests. */
+ switch (entry) {
+ case FW_CFG_NB_CPUS:
+ if (length == 2)
+ *((u16 *)address) = cpu_to_le16(5);
+ break;
+ case FW_CFG_FILE_DIR:
+ if (length == 4) {
+ *((u32 *)address) = cpu_to_be32(2);
+ plat->file_dir_offset = 1;
+ }
+ break;
+ default:
+ debug("%s got unsupported entry 0x%x\n", __func__,
+ entry);
+ }
+ } else if (plat->file_dir_offset && length == 64) {
+ file = address;
+ switch (plat->file_dir_offset) {
+ case 1:
+ file->size = cpu_to_be32(8);
+ file->select = cpu_to_be16(FW_CFG_FILE_FIRST);
+ strcpy(file->name, "test-one");
+ plat->file_dir_offset++;
+ break;
+ case 2:
+ file->size = cpu_to_be32(8);
+ file->select = cpu_to_be16(FW_CFG_FILE_FIRST + 1);
+ strcpy(file->name, "test-two");
+ plat->file_dir_offset++;
+ break;
+ }
+ }
+
+ /*
+ * Signal that we are finished. No-one checks this in sandbox --
+ * normally the platform-specific driver looks for it -- but let's
+ * replicate the behaviour in case someone relies on it later.
+ */
+ dma->control = 0;
+}
+
+static int qfw_sandbox_probe(struct udevice *dev)
+{
+ return qfw_register(dev);
+}
+
+static struct dm_qfw_ops qfw_sandbox_ops = {
+ .read_entry_io = qfw_sandbox_read_entry_io,
+ .read_entry_dma = qfw_sandbox_read_entry_dma,
+};
+
+U_BOOT_DRIVER(qfw_sandbox) = {
+ .name = "qfw_sandbox",
+ .id = UCLASS_QFW,
+ .plat_auto = sizeof(struct qfw_sandbox_plat),
+ .probe = qfw_sandbox_probe,
+ .ops = &qfw_sandbox_ops,
+};
+
+U_BOOT_DRVINFO(qfw_sandbox) = {
+ .name = "qfw_sandbox",
+};