
We minimally exercise the sandbox driver.
Signed-off-by: Asherah Connor ashe@kivikakk.ee ---
(no changes since v1)
arch/sandbox/dts/sandbox.dtsi | 4 ++ arch/sandbox/dts/test.dts | 4 ++ drivers/misc/Makefile | 11 ++- drivers/misc/qfw_sandbox.c | 129 ++++++++++++++++++++++++++++++++++ test/dm/Makefile | 1 + test/dm/qfw.c | 42 +++++++++++ 6 files changed, 185 insertions(+), 6 deletions(-) create mode 100644 drivers/misc/qfw_sandbox.c create mode 100644 test/dm/qfw.c
diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi index dc933f3bfc..7ce05b9662 100644 --- a/arch/sandbox/dts/sandbox.dtsi +++ b/arch/sandbox/dts/sandbox.dtsi @@ -390,6 +390,10 @@ sandbox_tee { compatible = "sandbox,tee"; }; + + qfw { + compatible = "sandbox,qemu-fw-cfg-mmio"; + }; };
&cros_ec { diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index d4195b45bb..4b3f8831d5 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -112,6 +112,10 @@ compatible = "sandbox,dsi-host"; };
+ qfw { + compatible = "sandbox,qemu-fw-cfg-mmio"; + }; + a-test { reg = <0 1>; compatible = "denx,u-boot-fdt-test"; diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index e6e1dfea95..ea04abd6c5 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -55,12 +55,11 @@ obj-$(CONFIG_NUVOTON_NCT6102D) += nuvoton_nct6102d.o obj-$(CONFIG_P2SB) += p2sb-uclass.o obj-$(CONFIG_PCA9551_LED) += pca9551_led.o obj-$(CONFIG_$(SPL_)PWRSEQ) += pwrseq-uclass.o -obj-$(CONFIG_QFW) += qfw.o -ifdef CONFIG_X86 -obj-$(CONFIG_QFW) += qfw_pio.o -endif -ifdef CONFIG_ARM -obj-$(CONFIG_QFW) += qfw_mmio.o +ifdef CONFIG_QFW +obj-y += qfw.o +obj-$(CONFIG_X86) += qfw_pio.o +obj-$(CONFIG_ARM) += qfw_mmio.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..fc7006ae19 --- /dev/null +++ b/drivers/misc/qfw_sandbox.c @@ -0,0 +1,129 @@ +// 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, +}; + +static const struct udevice_id qfw_sandbox_ids[] = { + { .compatible = "sandbox,qemu-fw-cfg-mmio" }, + {} +}; + +U_BOOT_DRIVER(qfw_sandbox) = { + .name = "qfw_sandbox", + .id = UCLASS_QFW, + .of_match = qfw_sandbox_ids, + .plat_auto = sizeof(struct qfw_sandbox_plat), + .probe = qfw_sandbox_probe, + .ops = &qfw_sandbox_ops, +}; diff --git a/test/dm/Makefile b/test/dm/Makefile index 6275ec56ea..bdca7ae613 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -95,5 +95,6 @@ obj-$(CONFIG_SCMI_FIRMWARE) += scmi.o ifneq ($(CONFIG_PINMUX),) obj-$(CONFIG_PINCONF) += pinmux.o endif +obj-$(CONFIG_QFW) += qfw.o endif endif # !SPL diff --git a/test/dm/qfw.c b/test/dm/qfw.c new file mode 100644 index 0000000000..51b1c42dda --- /dev/null +++ b/test/dm/qfw.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2021 Asherah Connor ashe@kivikakk.ee + */ + +#include <common.h> +#include <qfw.h> +#include <dm.h> +#include <asm/test.h> +#include <dm/test.h> +#include <test/ut.h> + +/* + * Exercise the device enough to be satisfied the initialisation and DMA + * interfaces work. + */ + +static int dm_test_qfw_cpus(struct unit_test_state *uts) +{ + struct udevice *dev; + + ut_assertok(uclass_first_device_err(UCLASS_QFW, &dev)); + ut_asserteq(5, qfw_online_cpus(dev)); + + return 0; +} + +DM_TEST(dm_test_qfw_cpus, UT_TESTF_SCAN_FDT); + +static int dm_test_qfw_firmware_list(struct unit_test_state *uts) +{ + struct udevice *dev; + struct fw_file *file; + + ut_assertok(uclass_first_device_err(UCLASS_QFW, &dev)); + ut_assertok(qfw_read_firmware_list(dev)); + ut_assertok_ptr((file = qfw_find_file(dev, "test-one"))); + + return 0; +} + +DM_TEST(dm_test_qfw_firmware_list, UT_TESTF_SCAN_FDT);