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