1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Functional tests for UCLASS_FFA  class
4  *
5  * Copyright 2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
6  *
7  * Authors:
8  *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
9  */
10 
11 #include <common.h>
12 #include <blk.h>
13 #include <console.h>
14 #include <dm.h>
15 #include <mapmem.h>
16 #include <dm/test.h>
17 #include <linux/bitops.h>
18 #include <test/test.h>
19 #include <test/ut.h>
20 #include "../../drivers/mtd/nvmxip/nvmxip.h"
21 
22 /* NVMXIP devices described in the device tree */
23 #define SANDBOX_NVMXIP_DEVICES 2
24 
25 /* reference device tree data for the probed devices */
26 static struct nvmxip_plat nvmqspi_refdata[SANDBOX_NVMXIP_DEVICES] = {
27 	{0x08000000, 9, 4096}, {0x08200000, 9, 2048}
28 };
29 
30 #define NVMXIP_BLK_START_PATTERN 0x1122334455667788ULL
31 #define NVMXIP_BLK_END_PATTERN 0xa1a2a3a4a5a6a7a8ULL
32 
33 /**
34  * dm_nvmxip_flash_sanity() - check flash data
35  * @uts: test state
36  * @device_idx:	the NVMXIP device index
37  * @buffer:	the user buffer where the blocks data is copied to
38  *
39  * Mode 1: When buffer is NULL, initialize the flash with pattern data at the start
40  * and at the end of each block. This pattern data will be used to check data consistency
41  * when verifying the data read.
42  * Mode 2: When the user buffer is provided in the argument (not NULL), compare the data
43  * of the start and the end of each block in the user buffer with the expected pattern data.
44  * Return an error when the check fails.
45  *
46  * Return:
47  *
48  * 0 on success. Otherwise, failure
49  */
dm_nvmxip_flash_sanity(struct unit_test_state * uts,u8 device_idx,void * buffer)50 static int dm_nvmxip_flash_sanity(struct unit_test_state *uts, u8 device_idx, void *buffer)
51 {
52 	int i;
53 	u64 *ptr;
54 	u8 *base;
55 	unsigned long blksz;
56 
57 	blksz = BIT(nvmqspi_refdata[device_idx].lba_shift);
58 
59 	if (!buffer) {
60 		/* Mode 1: point at the flash start address. Pattern data will be written */
61 		base = map_sysmem(nvmqspi_refdata[device_idx].phys_base, 0);
62 	} else {
63 		/* Mode 2: point at the user buffer containing the data read and to be verified */
64 		base = buffer;
65 	}
66 
67 	for (i = 0; i < nvmqspi_refdata[device_idx].lba ; i++) {
68 		ptr = (u64 *)(base + i * blksz);
69 
70 		/* write an 8 bytes pattern at the start of the current block */
71 		if (!buffer)
72 			*ptr = NVMXIP_BLK_START_PATTERN;
73 		else
74 			ut_asserteq_64(NVMXIP_BLK_START_PATTERN, *ptr);
75 
76 		ptr = (u64 *)((u8 *)ptr + blksz - sizeof(u64));
77 
78 		/* write an 8 bytes pattern at the end of the current block */
79 		if (!buffer)
80 			*ptr = NVMXIP_BLK_END_PATTERN;
81 		else
82 			ut_asserteq_64(NVMXIP_BLK_END_PATTERN, *ptr);
83 	}
84 
85 	if (!buffer)
86 		unmap_sysmem(base);
87 
88 	return 0;
89 }
90 
91 /**
92  * dm_test_nvmxip() - check flash data
93  * @uts: test state
94  * Return:
95  *
96  * CMD_RET_SUCCESS on success. Otherwise, failure
97  */
dm_test_nvmxip(struct unit_test_state * uts)98 static int dm_test_nvmxip(struct unit_test_state *uts)
99 {
100 	struct nvmxip_plat *plat_data = NULL;
101 	struct udevice *dev = NULL, *bdev = NULL;
102 	u8 device_idx;
103 	void *buffer = NULL;
104 	unsigned long flashsz;
105 
106 	/* set the flash content first for both devices */
107 	dm_nvmxip_flash_sanity(uts, 0, NULL);
108 	dm_nvmxip_flash_sanity(uts, 1, NULL);
109 
110 	/* probing all NVM XIP QSPI devices */
111 	for (device_idx = 0, uclass_first_device(UCLASS_NVMXIP, &dev);
112 	     dev;
113 	     uclass_next_device(&dev), device_idx++) {
114 		plat_data = dev_get_plat(dev);
115 
116 		/* device tree entries checks */
117 		ut_assertok(nvmqspi_refdata[device_idx].phys_base != plat_data->phys_base);
118 		ut_assertok(nvmqspi_refdata[device_idx].lba_shift != plat_data->lba_shift);
119 		ut_assertok(nvmqspi_refdata[device_idx].lba != plat_data->lba);
120 
121 		/* before reading all the flash blocks, let's calculate the flash size */
122 		flashsz = plat_data->lba << plat_data->lba_shift;
123 
124 		/* allocate the user buffer where to copy the blocks data to */
125 		buffer = calloc(flashsz, 1);
126 		ut_assertok(!buffer);
127 
128 		/* the block device is the child of the parent device probed with DT */
129 		ut_assertok(device_find_first_child(dev, &bdev));
130 
131 		/* reading all the flash blocks */
132 		ut_asserteq(plat_data->lba, blk_read(bdev, 0, plat_data->lba, buffer));
133 
134 		/* compare the data read from flash with the expected data */
135 		dm_nvmxip_flash_sanity(uts, device_idx, buffer);
136 
137 		free(buffer);
138 	}
139 
140 	ut_assertok(device_idx != SANDBOX_NVMXIP_DEVICES);
141 
142 	return CMD_RET_SUCCESS;
143 }
144 
145 DM_TEST(dm_test_nvmxip, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
146