aboutsummaryrefslogtreecommitdiff
path: root/test/dm/nvmxip.c
blob: f0ad47d4efe9313e480154f1da5e34c06db40eb4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// 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 <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;

	sandbox_set_enable_memio(true);

	/* 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);