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, §or_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, §or_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