]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
sandbox64: add a test case for UCLASS_NVMXIP
authorAbdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Mon, 17 Apr 2023 09:11:58 +0000 (10:11 +0100)
committerTom Rini <trini@konsulko.com>
Thu, 27 Apr 2023 21:01:15 +0000 (17:01 -0400)
provide a test for NVM XIP devices

The test case allows to make sure of the following:

- The NVM XIP QSPI devices are probed
- The DT entries are read correctly
- the data read from the flash by the NVMXIP block driver is correct

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
MAINTAINERS
test/dm/Makefile
test/dm/nvmxip.c [new file with mode: 0644]

index fd155ca878819eff5c06f971f83992b2a4e91326..0257526bc82ab5731bd4799362934b49667c5e7e 100644 (file)
@@ -1210,6 +1210,7 @@ S:        Maintained
 F:     doc/develop/driver-model/nvmxip.rst
 F:     doc/device-tree-bindings/nvmxip/nvmxip_qspi.txt
 F:     drivers/mtd/nvmxip/
+F:     test/dm/nvmxip.c
 
 NVMEM
 M:     Sean Anderson <seanga2@gmail.com>
index e15bdbf04bc32f12469115c041f8fc2ec0b77487..c8534b5cfa899aea9d65670e7a46f66f846c4cda 100644 (file)
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
+# Copyright 2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 
 obj-$(CONFIG_UT_DM) += test-dm.o
 
@@ -17,6 +18,10 @@ obj-$(CONFIG_UT_DM) += test-uclass.o
 obj-$(CONFIG_UT_DM) += core.o
 obj-$(CONFIG_UT_DM) += read.o
 obj-$(CONFIG_UT_DM) += phys2bus.o
+ifeq ($(CONFIG_NVMXIP_QSPI)$(CONFIG_SANDBOX64),yy)
+obj-y += nvmxip.o
+endif
+
 ifneq ($(CONFIG_SANDBOX),)
 ifeq ($(CONFIG_ACPIGEN),y)
 obj-y += acpi.o
diff --git a/test/dm/nvmxip.c b/test/dm/nvmxip.c
new file mode 100644 (file)
index 0000000..e934748
--- /dev/null
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Functional tests for UCLASS_FFA  class
+ *
+ * Copyright 2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <common.h>
+#include <blk.h>
+#include <console.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <dm/test.h>
+#include <linux/bitops.h>
+#include <test/test.h>
+#include <test/ut.h>
+#include "../../drivers/mtd/nvmxip/nvmxip.h"
+
+/* NVMXIP devices described in the device tree */
+#define SANDBOX_NVMXIP_DEVICES 2
+
+/* reference device tree data for the probed devices */
+static struct nvmxip_plat nvmqspi_refdata[SANDBOX_NVMXIP_DEVICES] = {
+       {0x08000000, 9, 4096}, {0x08200000, 9, 2048}
+};
+
+#define NVMXIP_BLK_START_PATTERN 0x1122334455667788ULL
+#define NVMXIP_BLK_END_PATTERN 0xa1a2a3a4a5a6a7a8ULL
+
+/**
+ * dm_nvmxip_flash_sanity() - check flash data
+ * @uts: test state
+ * @device_idx:        the NVMXIP device index
+ * @buffer:    the user buffer where the blocks data is copied to
+ *
+ * Mode 1: When buffer is NULL, initialize the flash with pattern data at the start
+ * and at the end of each block. This pattern data will be used to check data consistency
+ * when verifying the data read.
+ * Mode 2: When the user buffer is provided in the argument (not NULL), compare the data
+ * of the start and the end of each block in the user buffer with the expected pattern data.
+ * Return an error when the check fails.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int dm_nvmxip_flash_sanity(struct unit_test_state *uts, u8 device_idx, void *buffer)
+{
+       int i;
+       u64 *ptr;
+       u8 *base;
+       unsigned long blksz;
+
+       blksz = BIT(nvmqspi_refdata[device_idx].lba_shift);
+
+       if (!buffer) {
+               /* Mode 1: point at the flash start address. Pattern data will be written */
+               base = map_sysmem(nvmqspi_refdata[device_idx].phys_base, 0);
+       } else {
+               /* Mode 2: point at the user buffer containing the data read and to be verified */
+               base = buffer;
+       }
+
+       for (i = 0; i < nvmqspi_refdata[device_idx].lba ; i++) {
+               ptr = (u64 *)(base + i * blksz);
+
+               /* write an 8 bytes pattern at the start of the current block */
+               if (!buffer)
+                       *ptr = NVMXIP_BLK_START_PATTERN;
+               else
+                       ut_asserteq_64(NVMXIP_BLK_START_PATTERN, *ptr);
+
+               ptr = (u64 *)((u8 *)ptr + blksz - sizeof(u64));
+
+               /* write an 8 bytes pattern at the end of the current block */
+               if (!buffer)
+                       *ptr = NVMXIP_BLK_END_PATTERN;
+               else
+                       ut_asserteq_64(NVMXIP_BLK_END_PATTERN, *ptr);
+       }
+
+       if (!buffer)
+               unmap_sysmem(base);
+
+       return 0;
+}
+
+/**
+ * dm_test_nvmxip() - check flash data
+ * @uts: test state
+ * Return:
+ *
+ * CMD_RET_SUCCESS on success. Otherwise, failure
+ */
+static int dm_test_nvmxip(struct unit_test_state *uts)
+{
+       struct nvmxip_plat *plat_data = NULL;
+       struct udevice *dev = NULL, *bdev = NULL;
+       u8 device_idx;
+       void *buffer = NULL;
+       unsigned long flashsz;
+
+       /* set the flash content first for both devices */
+       dm_nvmxip_flash_sanity(uts, 0, NULL);
+       dm_nvmxip_flash_sanity(uts, 1, NULL);
+
+       /* probing all NVM XIP QSPI devices */
+       for (device_idx = 0, uclass_first_device(UCLASS_NVMXIP, &dev);
+            dev;
+            uclass_next_device(&dev), device_idx++) {
+               plat_data = dev_get_plat(dev);
+
+               /* device tree entries checks */
+               ut_assertok(nvmqspi_refdata[device_idx].phys_base != plat_data->phys_base);
+               ut_assertok(nvmqspi_refdata[device_idx].lba_shift != plat_data->lba_shift);
+               ut_assertok(nvmqspi_refdata[device_idx].lba != plat_data->lba);
+
+               /* before reading all the flash blocks, let's calculate the flash size */
+               flashsz = plat_data->lba << plat_data->lba_shift;
+
+               /* allocate the user buffer where to copy the blocks data to */
+               buffer = calloc(flashsz, 1);
+               ut_assertok(!buffer);
+
+               /* the block device is the child of the parent device probed with DT */
+               ut_assertok(device_find_first_child(dev, &bdev));
+
+               /* reading all the flash blocks */
+               ut_asserteq(plat_data->lba, blk_read(bdev, 0, plat_data->lba, buffer));
+
+               /* compare the data read from flash with the expected data */
+               dm_nvmxip_flash_sanity(uts, device_idx, buffer);
+
+               free(buffer);
+       }
+
+       ut_assertok(device_idx != SANDBOX_NVMXIP_DEVICES);
+
+       return CMD_RET_SUCCESS;
+}
+
+DM_TEST(dm_test_nvmxip, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);