Bug Summary

File:drivers/spi/spi_sdcard.c
Warning:line 548, column 3
Value stored to 'end_block_address' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name spi_sdcard.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -fno-delete-null-pointer-checks -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -ffreestanding -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/home/coreboot/node-root/workspace/coreboot_scanbuild -nostdsysteminc -nobuiltininc -resource-dir /opt/xgcc/lib/clang/17 -include src/include/kconfig.h -include src/include/rules.h -include src/commonlib/bsd/include/commonlib/bsd/compiler.h -I src -I src/include -I src/commonlib/include -I src/commonlib/bsd/include -I /cb-build/coreboot_scanbuild.0/SIFIVE_HIFIVE_UNMATCHED -I 3rdparty/vboot/firmware/include -I 3rdparty -D __BUILD_DIR__="/cb-build/coreboot_scanbuild.0/SIFIVE_HIFIVE_UNMATCHED" -D __COREBOOT__ -D __TIMELESS__ -I src/soc/sifive/fu740/include -I src/arch/riscv/include -D __ARCH_riscv__ -I src/arch/riscv/ -D __riscv -D __riscv_xlen=64 -D __riscv_flen=64 -D __RAMSTAGE__ -source-date-epoch 1715206807 -Os -Wwrite-strings -Wno-trigraphs -Wno-address-of-packed-member -std=gnu11 -fconst-strings -fdebug-compilation-dir=/home/coreboot/node-root/workspace/coreboot_scanbuild -ferror-limit 19 -fno-builtin -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-max-loop 10 -analyzer-output=plist-html -faddrsig -o /cb-build/coreboot_scanbuild.0/SIFIVE_HIFIVE_UNMATCHED-scanbuildtmp/2024-05-09-081030-2851123-1/report-lTXYRD.plist -x c src/drivers/spi/spi_sdcard.c
1/* SPDX-License-Identifier: GPL-2.0-only */
2#include <stdint.h>
3#include <string.h>
4#include <spi-generic.h>
5#include <spi_sdcard.h>
6#include <crc_byte.h>
7#include <commonlib/helpers.h>
8#include <console/console.h>
9
10#define SPI_SDCARD_DEBUG0 0
11
12#define dprintk(fmt, args...)do { if (0) { printk(7, fmt, args...); }} while (0) \
13 do { if (SPI_SDCARD_DEBUG0) { printk(BIOS_DEBUG7, fmt, ##args); }} while (0)
14
15#define SDCARD_TYPE_SDSC1 1
16#define SDCARD_TYPE_SDHC2 2
17#define SDCARD_TYPE_SDXC3 3
18
19/* CMD */
20#define GO_IDLE_STATE0 0
21#define SEND_OP_COND1 1
22#define SWITCH_FUNC6 6
23#define SEND_IF_COND8 8
24#define SEND_CSD9 9
25#define SEND_CID10 10
26#define STOP_TRANSMISSION12 12
27#define SEND_STATUS13 13
28#define SET_BLOCKLEN16 16
29#define READ_SINGLE_BLOCK17 17
30#define READ_MULTIPLEBLOCK18 18
31#define WRITE_BLOCK24 24
32#define WRITE_MULTIPLEBLOCK25 25
33#define PROGRAM_CSD27 27
34#define SET_WRITE_PROT28 28
35#define CLR_WRITE_PROT29 29
36#define SEND_WRITE_PROT30 30
37#define ERASE_WR_BLK_START_ADDR32 32
38#define ERASE_WR_BLK_END_ADDR33 33
39#define ERASE38 38
40#define LOCK_UNLOCK42 42
41#define APP_CMD55 55
42#define GEN_CMD56 56
43#define READ_OCR58 58
44#define CRC_ON_OFF59 59
45
46/* ACMD */
47#define SD_STATUS13 13
48#define SEND_NUM_WR_BLOCKS22 22
49#define SET_WR_BLK_ERASE_COUNT23 23
50#define SD_SEND_OP_COND41 41
51#define SET_CLR_CARD_DETECT42 42
52#define SEND_SCR51 51
53
54/* control tokens */
55#define CT_BLOCK_START0xfe 0xfe
56#define CT_MULTIPLE_BLOCK_START0xfc 0xfc
57#define CT_MULTIPLE_BLOCK_STOP0xfd 0xfd
58#define CT_RESPONSE_MASK0x1f 0x1f
59#define CT_RESPONSE_ACCEPTED0x05 0x05
60#define CT_RESPONSE_REJECTED_CRC0x0b 0x0b
61#define CT_RESPONSE_REJECTED_WRITE_ERR0x0d 0x0d
62
63/* response type */
64#define RSP_R10 0
65#define RSP_R1b1 1
66#define RSP_R22 2
67#define RSP_R33 3
68#define RSP_R44 4
69#define RSP_R55 5
70#define RSP_R77 7
71
72#define RSP_ERR_CARD_IS_LOCKED(1 << 0) (1 << 0)
73#define RSP_ERR_WP_ERASE_SKIP(1 << 1) (1 << 1)
74#define RSP_ERR_GENERAL(1 << 2) (1 << 2)
75#define RSP_ERR_CC(1 << 3) (1 << 3)
76#define RSP_ERR_ECC(1 << 4) (1 << 4)
77#define RSP_ERR_WP_VIOLATION(1 << 5) (1 << 5)
78#define RSP_ERR_ERASE_PARAM(1 << 6) (1 << 6)
79#define RSP_ERR_OUT_OF_RANGE(1 << 7) (1 << 7)
80#define RSP_ERR_IN_IDLE(1 << 8) (1 << 8)
81#define RSP_ERR_ERASE_RESET(1 << 9) (1 << 9)
82#define RSP_ERR_ILLEGAL_COMMAND(1 << 10) (1 << 10)
83#define RSP_ERR_COM_CRC(1 << 11) (1 << 11)
84#define RSP_ERR_ERASE_SEQUENCE(1 << 12) (1 << 12)
85#define RSP_ERR_ADDRESS(1 << 13) (1 << 13)
86#define RSP_ERR_PARAMETER(1 << 14) (1 << 14)
87
88#define BLOCK_SIZE512 512
89
90static unsigned long long extract_bits(uint8_t *buff,
91 int width, int start, int end)
92{
93 unsigned long long r = 0;
94 for (int i = end; i >= start; i--) {
95 int bitpos = width - i - 1;
96 int b = bitpos / 8;
97 int shift = 7 - bitpos % 8;
98 r = (r << 1) | ((buff[b] >> shift) & 1);
99 }
100 return r;
101}
102
103static void spi_sdcard_enable_cs(const struct spi_sdcard *card)
104{
105 spi_claim_bus(&card->slave);
106}
107
108static void spi_sdcard_disable_cs(const struct spi_sdcard *card)
109{
110 spi_release_bus(&card->slave);
111}
112
113static void spi_sdcard_sendbyte(const struct spi_sdcard *card, uint8_t b)
114{
115 dprintk("sdcard -> %#x\n", b)do { if (0) { printk(7, "sdcard -> %#x\n", b); }} while (0
)
;
116 spi_xfer(&card->slave, &b, 1, NULL((void *)0), 0);
117}
118
119static uint8_t spi_sdcard_recvbyte(const struct spi_sdcard *card)
120{
121 uint8_t b, t = 0xff;
122 spi_xfer(&card->slave, &t, 1, &b, 1);
123 dprintk("sdcard <- %#x\n", b)do { if (0) { printk(7, "sdcard <- %#x\n", b); }} while (0
)
;
124 return b;
125}
126
127static uint8_t spi_sdcard_calculate_command_crc(uint8_t cmd, uint32_t argument)
128{
129 uint8_t crc = 0;
130 crc = crc7_byte(crc, (cmd | 0x40) & 0x7f);
131 crc = crc7_byte(crc, (argument >> (3 * 8)) & 0xff);
132 crc = crc7_byte(crc, (argument >> (2 * 8)) & 0xff);
133 crc = crc7_byte(crc, (argument >> (1 * 8)) & 0xff);
134 crc = crc7_byte(crc, (argument >> (0 * 8)) & 0xff);
135 return crc | 1;
136}
137
138static int lookup_cmd_response_type(uint8_t cmd)
139{
140 switch (cmd) {
141 case GO_IDLE_STATE0:
142 case SEND_OP_COND1:
143 case SWITCH_FUNC6:
144 case SEND_CSD9:
145 case SEND_CID10:
146 case SET_BLOCKLEN16:
147 case READ_SINGLE_BLOCK17:
148 case READ_MULTIPLEBLOCK18:
149 case WRITE_BLOCK24:
150 case WRITE_MULTIPLEBLOCK25:
151 case PROGRAM_CSD27:
152 case SEND_WRITE_PROT30:
153 case ERASE_WR_BLK_START_ADDR32:
154 case ERASE_WR_BLK_END_ADDR33:
155 case LOCK_UNLOCK42:
156 case APP_CMD55:
157 case GEN_CMD56:
158 case CRC_ON_OFF59:
159 return RSP_R10;
160 case STOP_TRANSMISSION12:
161 case SET_WRITE_PROT28:
162 case CLR_WRITE_PROT29:
163 case ERASE38:
164 return RSP_R1b1;
165 case SEND_STATUS13:
166 return RSP_R22;
167 case READ_OCR58:
168 return RSP_R33;
169 case SEND_IF_COND8:
170 return RSP_R77;
171 }
172 return -1;
173}
174
175static int lookup_acmd_response_type(uint8_t cmd)
176{
177 switch (cmd) {
178 case SEND_NUM_WR_BLOCKS22:
179 case SET_WR_BLK_ERASE_COUNT23:
180 case SD_SEND_OP_COND41:
181 case SET_CLR_CARD_DETECT42:
182 case SEND_SCR51:
183 return RSP_R10;
184 case SD_STATUS13:
185 return RSP_R22;
186 }
187 return -1;
188}
189
190static int lookup_response_length(int response_type)
191{
192 switch (response_type) {
193 case RSP_R10:
194 case RSP_R1b1:
195 return 1;
196 case RSP_R22:
197 return 2;
198 case RSP_R33:
199 case RSP_R77:
200 return 5;
201 }
202 return -1;
203}
204
205static int response_resolve(int response_type, uint8_t *response,
206 uint32_t *out_register)
207{
208 __maybe_unused__attribute__((__unused__)) static const char * const sd_err[] = {
209 "Card is locked",
210 "wp erase skip | lock/unlock cmd failed",
211 "error",
212 "CC error",
213 "card err failed",
214 "wp violation",
215 "erase param",
216 "out of range | csd overwrite",
217 "in idle state",
218 "erase reset",
219 "illegal command",
220 "com crc error",
221 "erase sequence error",
222 "address error",
223 "parameter error"
224 };
225 uint8_t r1 = 0, r2 = 0;
226
227 if ((response_type == RSP_R10)
228 || (response_type == RSP_R1b1)
229 || (response_type == RSP_R22)
230 || (response_type == RSP_R33)
231 || (response_type == RSP_R77))
232 r1 = response[0];
233
234 if (response_type == RSP_R22)
235 r2 = response[1];
236
237 if (((response_type == RSP_R33) || (response_type == RSP_R77))
238 && (out_register != NULL((void *)0))) {
239 *out_register = 0;
240 *out_register = (*out_register << 8) | response[1];
241 *out_register = (*out_register << 8) | response[2];
242 *out_register = (*out_register << 8) | response[3];
243 *out_register = (*out_register << 8) | response[4];
244 }
245
246 if (r1 != 0 || r2 != 0) {
247 int i = 0;
248 uint16_t r = (r1 << 8) | r2;
249 while (r) {
250 if (r & 1)
251 dprintk("SDCARD ERROR: %s\n", sd_err[i])do { if (0) { printk(7, "SDCARD ERROR: %s\n", sd_err[i]); }} while
(0)
;
252 r = r >> 1;
253 i++;
254 }
255 return (r1 << 8) | r2;
256 }
257
258 return 0;
259}
260
261static int spi_sdcard_do_command_help(const struct spi_sdcard *card,
262 int is_acmd,
263 uint8_t cmd,
264 uint32_t argument,
265 uint32_t *out_register)
266{
267 int ret, type, length, wait;
268 uint8_t crc, c, response[5];
269
270 /* calculate crc for command */
271 crc = spi_sdcard_calculate_command_crc(cmd, argument);
272
273 if (is_acmd)
274 dprintk("\nsdcard execute acmd%d, argument = %#x, crc = %#x\n",do { if (0) { printk(7, "\nsdcard execute acmd%d, argument = %#x, crc = %#x\n"
, cmd, argument, crc); }} while (0)
275 cmd, argument, crc)do { if (0) { printk(7, "\nsdcard execute acmd%d, argument = %#x, crc = %#x\n"
, cmd, argument, crc); }} while (0)
;
276 else
277 dprintk("\nsdcard execute cmd%d, argument = %#x, crc = %#x\n",do { if (0) { printk(7, "\nsdcard execute cmd%d, argument = %#x, crc = %#x\n"
, cmd, argument, crc); }} while (0)
278 cmd, argument, crc)do { if (0) { printk(7, "\nsdcard execute cmd%d, argument = %#x, crc = %#x\n"
, cmd, argument, crc); }} while (0)
;
279
280 /* lookup response type of command */
281 if (!is_acmd)
282 type = lookup_cmd_response_type(cmd);
283 else
284 type = lookup_acmd_response_type(cmd);
285
286 /* lookup response length of command */
287 length = lookup_response_length(type);
288
289 /* enable cs */
290 spi_sdcard_enable_cs(card);
291
292 /* just delay 8 clocks */
293 spi_sdcard_recvbyte(card);
294
295 /* send command */
296 spi_sdcard_sendbyte(card, (cmd | 0x40) & 0x7f);
297 /* send argument */
298 spi_sdcard_sendbyte(card, (argument >> (8 * 3)) & 0xff);
299 spi_sdcard_sendbyte(card, (argument >> (8 * 2)) & 0xff);
300 spi_sdcard_sendbyte(card, (argument >> (8 * 1)) & 0xff);
301 spi_sdcard_sendbyte(card, (argument >> (8 * 0)) & 0xff);
302 /* send crc */
303 spi_sdcard_sendbyte(card, crc);
304
305 /* waiting for response */
306 wait = 0xffff;
307 while (((c = spi_sdcard_recvbyte(card)) & 0x80) && --wait)
308 ;
309 if (!wait) {
310 spi_sdcard_disable_cs(card);
311 return -1; /* timeout */
312 }
313
314 /* obtain response */
315 for (int i = 0; i < length; i++) {
316 response[i] = c;
317 c = spi_sdcard_recvbyte(card);
318 }
319
320 if (type == RSP_R1b1) {
321 /* waiting done */
322 wait = 0xffffff;
323 while (c == 0 && --wait)
324 c = spi_sdcard_recvbyte(card);
325 if (!wait) {
326 spi_sdcard_disable_cs(card);
327 return -1; /* timeout */
328 }
329 }
330
331 spi_sdcard_disable_cs(card);
332
333 ret = response_resolve(type, response, out_register);
334
335 return ret;
336}
337
338static int spi_sdcard_do_command(const struct spi_sdcard *card,
339 uint8_t cmd,
340 uint32_t argument,
341 uint32_t *out_register)
342{
343 return spi_sdcard_do_command_help(card, 0, cmd, argument, out_register);
344}
345
346static int spi_sdcard_do_app_command(const struct spi_sdcard *card,
347 uint8_t cmd,
348 uint32_t argument,
349 uint32_t *out_register)
350{
351 /* CMD55 */
352 if (spi_sdcard_do_command(card, APP_CMD55, 0, NULL((void *)0)))
353 return -1;
354
355 return spi_sdcard_do_command_help(card, 1, cmd, argument, out_register);
356}
357
358size_t spi_sdcard_size(const struct spi_sdcard *card)
359{
360 int wait;
361 uint8_t csd[16];
362 uint16_t c = 0;
363
364 /* CMD9, send csd (128bits register) */
365 if (spi_sdcard_do_command(card, SEND_CSD9, 0, NULL((void *)0)))
366 return -1;
367
368 /* enable CS */
369 spi_sdcard_enable_cs(card);
370
371 /* waiting start block token */
372 wait = 0xffff;
373 while ((spi_sdcard_recvbyte(card) != CT_BLOCK_START0xfe) && --wait)
374 ;
375 if (!wait) {
376 spi_sdcard_disable_cs(card);
377 return -1;
378 }
379
380 /* receive data */
381 for (int i = 0; i < 16; i++) {
382 csd[i] = spi_sdcard_recvbyte(card);
383 c = crc16_byte(c, csd[i]);
384 }
385
386 /* receive crc and verify check sum */
387 if (((c >> 8) & 0xff) != spi_sdcard_recvbyte(card)) {
388 spi_sdcard_disable_cs(card);
389 return -1;
390 }
391 if (((c >> 0) & 0xff) != spi_sdcard_recvbyte(card)) {
392 spi_sdcard_disable_cs(card);
393 return -1;
394 }
395
396 /* disable cs */
397 spi_sdcard_disable_cs(card);
398
399 if (extract_bits(csd, 128, 126, 127) == 0) {
400 /* csd version 1.0 */
401 size_t c_size = extract_bits(csd, 128, 62, 73);
402 size_t mult = extract_bits(csd, 128, 47, 49);
403 size_t read_bl_len = extract_bits(csd, 128, 80, 83);
404 return (c_size + 1) * mult * (1 << read_bl_len);
405 }
406
407 if (extract_bits(csd, 128, 126, 127) == 1) {
408 /* csd version 2.0 */
409 size_t c_size = extract_bits(csd, 128, 48, 69);
410 return (c_size + 1) * 512 * 1024;
411 }
412
413 return -1;
414}
415
416int spi_sdcard_init(struct spi_sdcard *card,
417 const unsigned int bus, const unsigned int cs)
418{
419 int resolve, wait;
420 uint32_t ocr;
421
422 /* initialize spi controller */
423 spi_setup_slave(bus, cs, &card->slave);
424
425 /* must wait at least 74 clock ticks after reset
426 * disable cs pin to enter spi mode */
427 spi_sdcard_disable_cs(card);
428 for (int i = 0; i < 10; i++)
429 spi_sdcard_sendbyte(card, 0xff);
430
431 /* CMD0, reset sdcard */
432 wait = 0xffff;
433 while ((spi_sdcard_do_command(card, GO_IDLE_STATE0, 0, NULL((void *)0))
434 != RSP_ERR_IN_IDLE(1 << 8)) && --wait)
435 ;
436 if (!wait)
437 return -1; /* timeout */
438
439 /* CMD8 */
440 resolve = spi_sdcard_do_command(card, SEND_IF_COND8, 0x1aa, NULL((void *)0));
441 if (resolve & RSP_ERR_ILLEGAL_COMMAND(1 << 10)) {
442 /* ACMD41, initialize card */
443 wait = 0xffff;
444 while ((resolve = spi_sdcard_do_app_command(card,
445 SD_SEND_OP_COND41, 0, NULL((void *)0))) && --wait)
446 ;
447 if ((resolve & RSP_ERR_ILLEGAL_COMMAND(1 << 10)) || !wait) {
448 wait = 0xffff;
449 /* CMD1, initialize card for 2.1mm SD Memory Card */
450 while (spi_sdcard_do_app_command(card, SEND_OP_COND1,
451 0, NULL((void *)0)) && --wait)
452 ;
453 if (!wait)
454 return -1; /* unknown card */
455 }
456 } else {
457 /* ACMD41, initialize card */
458 wait = 0xffff;
459 while (spi_sdcard_do_app_command(card, SD_SEND_OP_COND41,
460 0x40000000, NULL((void *)0)) && --wait)
461 ;
462 if (!wait)
463 return -1;
464 }
465
466 /* CMD58, read ocr register */
467 if (spi_sdcard_do_command(card, READ_OCR58, 0, &ocr))
468 return -1;
469
470 /* CMD16, set block length to 512 bytes */
471 if (spi_sdcard_do_command(card, SET_BLOCKLEN16, 512, NULL((void *)0)))
472 return -1;
473
474 /* CCS is bit30 of ocr register
475 * CCS = 0 -> SDSC
476 * CCS = 1 -> SDHC/SDXC
477 * */
478 if ((ocr & 0x40000000) == 0)
479 card->type = SDCARD_TYPE_SDSC1;
480 else {
481 /* size > 32G -> SDXC */
482 if (spi_sdcard_size(card) > 32LL * 1024 * 1024 * 1024)
483 card->type = SDCARD_TYPE_SDXC3;
484 else
485 card->type = SDCARD_TYPE_SDHC2;
486 }
487
488 return 0;
489}
490
491int spi_sdcard_single_read(const struct spi_sdcard *card,
492 size_t block_address,
493 void *buff)
494{
495 int wait;
496 uint16_t c = 0;
497
498 if (card->type == SDCARD_TYPE_SDSC1)
499 block_address = block_address * 512;
500
501 /* CMD17, start single block read */
502 if (spi_sdcard_do_command(card, READ_SINGLE_BLOCK17, block_address, NULL((void *)0)))
503 return -1;
504
505 /* enable cs */
506 spi_sdcard_enable_cs(card);
507
508 /* waiting start block token */
509 wait = 0xffff;
510 while ((spi_sdcard_recvbyte(card) != CT_BLOCK_START0xfe) && --wait)
511 ;
512 if (!wait) { /* timeout */
513 spi_sdcard_disable_cs(card);
514 return -1;
515 }
516
517 /* receive data */
518 for (int i = 0; i < 512; i++) {
519 ((uint8_t *)buff)[i] = spi_sdcard_recvbyte(card);
520 c = crc16_byte(c, ((uint8_t *)buff)[i]);
521 }
522
523 /* receive crc and verify check sum */
524 if (((c >> 8) & 0xff) != spi_sdcard_recvbyte(card)) {
525 spi_sdcard_disable_cs(card);
526 return -1;
527 }
528 if (((c >> 0) & 0xff) != spi_sdcard_recvbyte(card)) {
529 spi_sdcard_disable_cs(card);
530 return -1;
531 }
532
533 /* disable cs */
534 spi_sdcard_disable_cs(card);
535
536 return 0;
537}
538
539int spi_sdcard_multiple_read(const struct spi_sdcard *card,
540 size_t start_block_address,
541 size_t end_block_address,
542 void *buff)
543{
544 int wait;
545 int block_num = end_block_address - start_block_address + 1;
546 if (card->type == SDCARD_TYPE_SDSC1) {
547 start_block_address = start_block_address * 512;
548 end_block_address = end_block_address * 512;
Value stored to 'end_block_address' is never read
549 }
550 /* CMD18, start multiple block read */
551 if (spi_sdcard_do_command(card,
552 READ_MULTIPLEBLOCK18, start_block_address, NULL((void *)0)))
553 return -1;
554
555 /* enable cs */
556 spi_sdcard_enable_cs(card);
557
558 for (int i = 0; i < block_num; i++) {
559 uint16_t c = 0;
560
561 /* waiting start block token */
562 wait = 0xffff;
563 while ((spi_sdcard_recvbyte(card) != CT_BLOCK_START0xfe) && --wait)
564 ;
565 if (!wait) { /* timeout */
566 spi_sdcard_disable_cs(card);
567 return -1;
568 }
569
570 /* receive data */
571 for (int k = 0; k < 512; k++) {
572 uint8_t tmp = spi_sdcard_recvbyte(card);
573 ((uint8_t *)buff)[512 * i + k] = tmp;
574 c = crc16_byte(c, tmp);
575 }
576
577 /* receive crc and verify check sum */
578 if (((c >> 8) & 0xff) != spi_sdcard_recvbyte(card)) {
579 spi_sdcard_disable_cs(card);
580 return -1;
581 }
582 if (((c >> 0) & 0xff) != spi_sdcard_recvbyte(card)) {
583 spi_sdcard_disable_cs(card);
584 return -1;
585 }
586 }
587
588 /* disable cs */
589 spi_sdcard_disable_cs(card);
590
591 if (spi_sdcard_do_command(card, STOP_TRANSMISSION12, 0, NULL((void *)0)))
592 if (spi_sdcard_do_command(card, SEND_STATUS13, 0, NULL((void *)0)))
593 return -1;
594
595 return 0;
596}
597
598int spi_sdcard_read(const struct spi_sdcard *card,
599 void *dest,
600 size_t offset,
601 size_t count)
602{
603 size_t start_block_address = offset / BLOCK_SIZE512;
604 size_t end_block_address = (offset + count - 1) / BLOCK_SIZE512;
605 size_t has_begin = !!(offset % BLOCK_SIZE512);
606 size_t has_end = !!((offset + count) % BLOCK_SIZE512);
607
608 if (start_block_address == end_block_address) {
609 uint8_t tmp[BLOCK_SIZE512];
610 size_t o = offset % BLOCK_SIZE512;
611 size_t l = count;
612 if (spi_sdcard_single_read(card, start_block_address, tmp))
613 return -1;
614 memcpy(dest, tmp + o, l);
615 return 0;
616 }
617
618 if (has_begin) {
619 uint8_t tmp[BLOCK_SIZE512];
620 size_t o = offset % BLOCK_SIZE512;
621 size_t l = BLOCK_SIZE512 - o;
622 if (spi_sdcard_single_read(card, start_block_address, tmp))
623 return -1;
624 memcpy(dest, tmp + o, l);
625 }
626
627 if (start_block_address + has_begin <= end_block_address - has_end) {
628 size_t start_lba = start_block_address + has_begin;
629 size_t end_lba = end_block_address - has_end;
630 size_t o = has_begin ? BLOCK_SIZE512 - offset % BLOCK_SIZE512 : 0;
631 if (start_lba < end_lba) {
632 if (spi_sdcard_multiple_read(card, start_lba, end_lba,
633 dest + o))
634 return -1;
635 } else {
636 if (spi_sdcard_single_read(card, start_lba, dest + o))
637 return -1;
638 }
639 }
640
641 if (has_end) {
642 uint8_t tmp[BLOCK_SIZE512];
643 size_t o = 0;
644 size_t l = (offset + count) % BLOCK_SIZE512;
645 if (spi_sdcard_single_read(card, end_block_address, tmp))
646 return -1;
647 memcpy(dest + count - l, tmp + o, l);
648 }
649
650 return 0;
651}
652
653int spi_sdcard_single_write(const struct spi_sdcard *card,
654 size_t block_address,
655 void *buff)
656{
657 int wait;
658 uint16_t c = 0;
659 if (card->type == SDCARD_TYPE_SDSC1)
660 block_address = block_address * 512;
661
662 if (spi_sdcard_do_command(card, WRITE_BLOCK24, block_address, NULL((void *)0)))
663 return -1;
664
665 /* enable cs */
666 spi_sdcard_enable_cs(card);
667
668 /* send start block token */
669 spi_sdcard_sendbyte(card, CT_BLOCK_START0xfe);
670
671 /* send data */
672 for (int i = 0; i < 512; i++) {
673 spi_sdcard_sendbyte(card, ((uint8_t *)buff)[i]);
674 c = crc16_byte(c, ((uint8_t *)buff)[i]);
675 }
676
677 /* send crc check sum */
678 spi_sdcard_sendbyte(card, 0xff & (c >> 8));
679 spi_sdcard_sendbyte(card, 0xff & (c >> 0));
680
681 /* receive and verify data response token */
682 c = spi_sdcard_recvbyte(card);
683 if ((c & CT_RESPONSE_MASK0x1f) != CT_RESPONSE_ACCEPTED0x05) {
684 spi_sdcard_disable_cs(card);
685 return -1;
686 }
687
688 wait = 0xffff;
689 while ((spi_sdcard_recvbyte(card) == 0) && --wait)
690 ;/* wait for complete */
691 if (!wait) {
692 spi_sdcard_disable_cs(card);
693 return -1;
694 }
695
696 /* disable cs */
697 spi_sdcard_disable_cs(card);
698
699 return 0;
700}
701
702int spi_sdcard_multiple_write(const struct spi_sdcard *card,
703 size_t start_block_address,
704 size_t end_block_address,
705 void *buff)
706{
707 int wait, ret = 0;
708 int block_num = end_block_address - start_block_address + 1;
709 if (card->type == SDCARD_TYPE_SDSC1) {
710 start_block_address = start_block_address * 512;
711 end_block_address = end_block_address * 512;
712 }
713
714 if (spi_sdcard_do_command(card, WRITE_MULTIPLEBLOCK25,
715 start_block_address, NULL((void *)0)))
716 return -1;
717
718 /* enable cs */
719 spi_sdcard_enable_cs(card);
720
721 for (int i = 0; i < block_num; i++) {
722 uint16_t c = 0;
723
724 ret = -1;
725
726 /* send start block token */
727 spi_sdcard_sendbyte(card, CT_MULTIPLE_BLOCK_START0xfc);
728
729 /* send data */
730 for (int k = 0; k < 512; k++) {
731 uint8_t tmp = ((uint8_t *)buff)[512 * i + k];
732 spi_sdcard_sendbyte(card, tmp);
733 c = crc16_byte(c, tmp);
734 }
735
736 /* send crc check sum */
737 spi_sdcard_sendbyte(card, 0xff & (c >> 8));
738 spi_sdcard_sendbyte(card, 0xff & (c >> 0));
739
740 /* receive and verify data response token */
741 c = spi_sdcard_recvbyte(card);
742 if ((c & CT_RESPONSE_MASK0x1f) != CT_RESPONSE_ACCEPTED0x05)
743 break;
744
745 wait = 0xffff;
746 while ((spi_sdcard_recvbyte(card) == 0) && --wait)
747 ;/* wait for complete */
748 if (!wait)
749 break;
750
751 ret = 0;
752 }
753
754 /* send stop transmission token */
755 spi_sdcard_sendbyte(card, CT_MULTIPLE_BLOCK_STOP0xfd);
756
757 /* disable cs */
758 spi_sdcard_disable_cs(card);
759
760 if (spi_sdcard_do_command(card, STOP_TRANSMISSION12, 0, NULL((void *)0)))
761 if (spi_sdcard_do_command(card, SEND_STATUS13, 0, NULL((void *)0)))
762 return -1;
763
764 return ret;
765}
766
767int spi_sdcard_erase(const struct spi_sdcard *card,
768 size_t start_block_address,
769 size_t end_block_address)
770{
771 if (card->type == SDCARD_TYPE_SDSC1) {
772 start_block_address = start_block_address * 512;
773 end_block_address = end_block_address * 512;
774 }
775
776 /* CMD32, set erase start address */
777 if (spi_sdcard_do_command(card, ERASE_WR_BLK_START_ADDR32,
778 start_block_address, NULL((void *)0)))
779 return -1;
780
781 /* CMD33, set erase end address */
782 if (spi_sdcard_do_command(card, ERASE_WR_BLK_END_ADDR33,
783 end_block_address, NULL((void *)0)))
784 return -1;
785
786 /* CMD38, erase */
787 if (spi_sdcard_do_command(card, ERASE38, 0, NULL((void *)0)))
788 return -1;
789
790 return 0;
791}
792
793int spi_sdcard_erase_all(const struct spi_sdcard *card)
794{
795 return spi_sdcard_erase(card, 0, spi_sdcard_size(card) / BLOCK_SIZE512);
796}