1 /*
2  * Copyright 2022 NXP
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/sd/sdmmc.h>
9 #include <zephyr/device.h>
10 #include <zephyr/drivers/disk.h>
11 #include <zephyr/ztest.h>
12 
13 
14 #define SECTOR_COUNT 32
15 #define SECTOR_SIZE 512 /* subsystem should set all cards to 512 byte blocks */
16 #define BUF_SIZE SECTOR_SIZE * SECTOR_COUNT
17 static const struct device *const sdhc_dev = DEVICE_DT_GET(DT_ALIAS(sdhc0));
18 static struct sd_card card;
19 static uint8_t buf[BUF_SIZE] __aligned(CONFIG_SDHC_BUFFER_ALIGNMENT);
20 static uint8_t check_buf[BUF_SIZE] __aligned(CONFIG_SDHC_BUFFER_ALIGNMENT);
21 static uint32_t sector_size;
22 static uint32_t sector_count;
23 
24 #define SDMMC_UNALIGN_OFFSET 1
25 
26 
27 /*
28  * Verify that SD stack can initialize an SD card
29  * This test must run first, to ensure the card is initialized.
30  */
ZTEST(sd_stack,test_0_init)31 ZTEST(sd_stack, test_0_init)
32 {
33 	int ret;
34 
35 	zassert_true(device_is_ready(sdhc_dev), "SDHC device is not ready");
36 
37 	ret = sd_is_card_present(sdhc_dev);
38 	zassert_equal(ret, 1, "SD card not present in slot");
39 
40 	ret = sd_init(sdhc_dev, &card);
41 	zassert_equal(ret, 0, "Card initialization failed");
42 }
43 
44 /* Verify that SD stack returns valid IOCTL values */
ZTEST(sd_stack,test_ioctl)45 ZTEST(sd_stack, test_ioctl)
46 {
47 	int ret;
48 
49 	ret = sdmmc_ioctl(&card, DISK_IOCTL_GET_SECTOR_COUNT, &sector_count);
50 	zassert_equal(ret, 0, "IOCTL sector count read failed");
51 	TC_PRINT("SD card reports sector count of %d\n", sector_count);
52 
53 	ret = sdmmc_ioctl(&card, DISK_IOCTL_GET_SECTOR_SIZE, &sector_size);
54 	zassert_equal(ret, 0, "IOCTL sector size read failed");
55 	TC_PRINT("SD card reports sector size of %d\n", sector_size);
56 }
57 
58 
59 /* Verify that SD stack can read from an SD card */
ZTEST(sd_stack,test_read)60 ZTEST(sd_stack, test_read)
61 {
62 	int ret;
63 	int block_addr = 0;
64 
65 	/* Try simple reads from start of SD card */
66 
67 	ret = sdmmc_read_blocks(&card, buf, block_addr, 1);
68 	zassert_equal(ret, 0, "Single block card read failed");
69 
70 	ret = sdmmc_read_blocks(&card, buf, block_addr, SECTOR_COUNT / 2);
71 	zassert_equal(ret, 0, "Multiple block card read failed");
72 
73 	/* Try a series of reads from the same block */
74 	block_addr = sector_count / 2;
75 	for (int i = 0; i < 10; i++) {
76 		ret = sdmmc_read_blocks(&card, buf, block_addr, SECTOR_COUNT);
77 		zassert_equal(ret, 0, "Multiple reads from same addr failed");
78 	}
79 	/* Verify that out of bounds read fails */
80 	block_addr = sector_count;
81 	ret = sdmmc_read_blocks(&card, buf, block_addr, 1);
82 	zassert_not_equal(ret, 0, "Out of bounds read should fail");
83 
84 	block_addr = sector_count - 2;
85 	ret = sdmmc_read_blocks(&card, buf, block_addr, 2);
86 	zassert_equal(ret, 0, "Read from end of card failed");
87 
88 	/* Verify that unaligned reads work */
89 	block_addr = 3;
90 	ret = sdmmc_read_blocks(&card, buf + SDMMC_UNALIGN_OFFSET,
91 		block_addr, SECTOR_COUNT - 1);
92 	zassert_equal(ret, 0, "Unaligned read failed");
93 }
94 
95 /* Verify that SD stack can write to an SD card */
ZTEST(sd_stack,test_write)96 ZTEST(sd_stack, test_write)
97 {
98 	int ret;
99 	int block_addr = 0;
100 
101 	/* Try simple writes from start of SD card */
102 
103 	ret = sdmmc_write_blocks(&card, buf, block_addr, 1);
104 	zassert_equal(ret, 0, "Single block card write failed");
105 
106 	ret = sdmmc_write_blocks(&card, buf, block_addr, SECTOR_COUNT / 2);
107 	zassert_equal(ret, 0, "Multiple block card write failed");
108 
109 	/* Try a series of reads from the same block */
110 	block_addr = sector_count / 2;
111 	for (int i = 0; i < 10; i++) {
112 		ret = sdmmc_write_blocks(&card, buf, block_addr, SECTOR_COUNT);
113 		zassert_equal(ret, 0, "Multiple writes to same addr failed");
114 	}
115 	/* Verify that out of bounds write fails */
116 	block_addr = sector_count;
117 	ret = sdmmc_write_blocks(&card, buf, block_addr, 1);
118 	zassert_not_equal(ret, 0, "Out of bounds write should fail");
119 
120 	block_addr = sector_count - 2;
121 	ret = sdmmc_write_blocks(&card, buf, block_addr, 2);
122 	zassert_equal(ret, 0, "Write to end of card failed");
123 
124 	/* Verify that unaligned writes work */
125 	block_addr = 3;
126 	ret = sdmmc_write_blocks(&card, buf + SDMMC_UNALIGN_OFFSET,
127 		block_addr, SECTOR_COUNT - 1);
128 	zassert_equal(ret, 0, "Unaligned write failed");
129 }
130 
131 /* Test reads and writes interleaved, to verify data is making it on disk */
ZTEST(sd_stack,test_rw)132 ZTEST(sd_stack, test_rw)
133 {
134 	int ret;
135 	int block_addr = 0;
136 
137 	/* Zero the write buffer */
138 	memset(buf, 0, BUF_SIZE);
139 	memset(check_buf, 0, BUF_SIZE);
140 	ret = sdmmc_write_blocks(&card, buf, block_addr, SECTOR_COUNT / 2);
141 	zassert_equal(ret, 0, "Write to card failed");
142 	/* Verify that a read from this area is empty */
143 	ret = sdmmc_read_blocks(&card, buf, block_addr, SECTOR_COUNT / 2);
144 	zassert_equal(ret, 0, "Read from card failed");
145 	zassert_mem_equal(buf, check_buf, BUF_SIZE,
146 		"Read of erased area was not zero");
147 
148 	/* Now write nonzero data block */
149 	for (int i = 0; i < sizeof(buf); i++) {
150 		check_buf[i] = buf[i] = (uint8_t)i;
151 	}
152 
153 	ret = sdmmc_write_blocks(&card, buf, block_addr, SECTOR_COUNT);
154 	zassert_equal(ret, 0, "Write to card failed");
155 	/* Clear the read buffer, then write to it again */
156 	memset(buf, 0, BUF_SIZE);
157 	ret = sdmmc_read_blocks(&card, buf, block_addr, SECTOR_COUNT);
158 	zassert_equal(ret, 0, "Read from card failed");
159 	zassert_mem_equal(buf, check_buf, BUF_SIZE,
160 		"Read of written area was not correct");
161 
162 	block_addr = (sector_count / 3);
163 	for (int i = 0; i < 10; i++) {
164 		/* Verify that unaligned writes work */
165 		ret = sdmmc_write_blocks(&card, buf + SDMMC_UNALIGN_OFFSET,
166 			block_addr, SECTOR_COUNT - 1);
167 		zassert_equal(ret, 0, "Write to card failed");
168 		/* Zero check buffer and read into it */
169 		memset(check_buf + SDMMC_UNALIGN_OFFSET, 0,
170 			(SECTOR_COUNT - 1) * sector_size);
171 		ret = sdmmc_read_blocks(&card, check_buf + SDMMC_UNALIGN_OFFSET,
172 			block_addr, (SECTOR_COUNT - 1));
173 		zassert_equal(ret, 0, "Read from card failed");
174 		zassert_mem_equal(buf + SDMMC_UNALIGN_OFFSET,
175 			check_buf + SDMMC_UNALIGN_OFFSET,
176 			(SECTOR_COUNT - 1) * sector_size,
177 			"Unaligned read of written area was not correct");
178 	}
179 }
180 
181 /* Simply dump the card configuration. */
ZTEST(sd_stack,test_card_config)182 ZTEST(sd_stack, test_card_config)
183 {
184 	switch (card.card_voltage) {
185 	case SD_VOL_1_2_V:
186 		TC_PRINT("Card voltage: 1.2V\n");
187 		break;
188 	case SD_VOL_1_8_V:
189 		TC_PRINT("Card voltage: 1.8V\n");
190 		break;
191 	case SD_VOL_3_0_V:
192 		TC_PRINT("Card voltage: 3.0V\n");
193 		break;
194 	case SD_VOL_3_3_V:
195 		TC_PRINT("Card voltage: 3.3V\n");
196 		break;
197 	default:
198 		zassert_unreachable("Card voltage is not known value");
199 	}
200 	zassert_equal(card.status, CARD_INITIALIZED, "Card status is not OK");
201 	switch (card.card_speed) {
202 	case SD_TIMING_SDR12:
203 		TC_PRINT("Card timing: SDR12\n");
204 		break;
205 	case SD_TIMING_SDR25:
206 		TC_PRINT("Card timing: SDR25\n");
207 		break;
208 	case SD_TIMING_SDR50:
209 		TC_PRINT("Card timing: SDR50\n");
210 		break;
211 	case SD_TIMING_SDR104:
212 		TC_PRINT("Card timing: SDR104\n");
213 		break;
214 	case SD_TIMING_DDR50:
215 		TC_PRINT("Card timing: DDR50\n");
216 		break;
217 	default:
218 		zassert_unreachable("Card timing is not known value");
219 	}
220 	switch (card.type) {
221 	case CARD_SDIO:
222 		TC_PRINT("Card type: SDIO\n");
223 		break;
224 	case CARD_SDMMC:
225 		TC_PRINT("Card type: SDMMC\n");
226 		break;
227 	case CARD_COMBO:
228 		TC_PRINT("Card type: combo card\n");
229 		break;
230 	default:
231 		zassert_unreachable("Card type is not known value");
232 	}
233 	if (card.sd_version >= SD_SPEC_VER3_0) {
234 		TC_PRINT("Card spec: 3.0\n");
235 	} else if (card.sd_version >= SD_SPEC_VER2_0) {
236 		TC_PRINT("Card spec: 2.0\n");
237 	} else if (card.sd_version >= SD_SPEC_VER1_1) {
238 		TC_PRINT("Card spec: 1.1\n");
239 	} else if (card.sd_version >= SD_SPEC_VER1_0) {
240 		TC_PRINT("Card spec: 1.0\n");
241 	} else {
242 		zassert_unreachable("Card spec is unknown value");
243 	}
244 }
245 
246 ZTEST_SUITE(sd_stack, NULL, NULL, NULL, NULL, NULL);
247