soc/intel/alderlake: Add ADL-P 4+4 with 28W TDP
[coreboot.git] / src / drivers / spi / spi_sdcard.c
blobe930b50b1349504af42a47331d5bde443c2361c0
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>
10 //#define SPI_SDCARD_DEBUG
12 #ifdef SPI_SDCARD_DEBUG
13 #define dprintk(fmt, args...) \
14 printk(BIOS_DEBUG, fmt, ##args)
15 #else
16 #define dprintk(fmt, args...) \
17 do {} while (0)
18 #endif
20 #define SDCARD_TYPE_SDSC 1
21 #define SDCARD_TYPE_SDHC 2
22 #define SDCARD_TYPE_SDXC 3
24 /* CMD */
25 #define GO_IDLE_STATE 0
26 #define SEND_OP_COND 1
27 #define SWITCH_FUNC 6
28 #define SEND_IF_COND 8
29 #define SEND_CSD 9
30 #define SEND_CID 10
31 #define STOP_TRANSMISSION 12
32 #define SEND_STATUS 13
33 #define SET_BLOCKLEN 16
34 #define READ_SINGLE_BLOCK 17
35 #define READ_MULTIPLEBLOCK 18
36 #define WRITE_BLOCK 24
37 #define WRITE_MULTIPLEBLOCK 25
38 #define PROGRAM_CSD 27
39 #define SET_WRITE_PROT 28
40 #define CLR_WRITE_PROT 29
41 #define SEND_WRITE_PROT 30
42 #define ERASE_WR_BLK_START_ADDR 32
43 #define ERASE_WR_BLK_END_ADDR 33
44 #define ERASE 38
45 #define LOCK_UNLOCK 42
46 #define APP_CMD 55
47 #define GEN_CMD 56
48 #define READ_OCR 58
49 #define CRC_ON_OFF 59
51 /* ACMD */
52 #define SD_STATUS 13
53 #define SEND_NUM_WR_BLOCKS 22
54 #define SET_WR_BLK_ERASE_COUNT 23
55 #define SD_SEND_OP_COND 41
56 #define SET_CLR_CARD_DETECT 42
57 #define SEND_SCR 51
59 /* control tokens */
60 #define CT_BLOCK_START 0xfe
61 #define CT_MULTIPLE_BLOCK_START 0xfc
62 #define CT_MULTIPLE_BLOCK_STOP 0xfd
63 #define CT_RESPONSE_MASK 0x1f
64 #define CT_RESPONSE_ACCEPTED 0x05
65 #define CT_RESPONSE_REJECTED_CRC 0x0b
66 #define CT_RESPONSE_REJECTED_WRITE_ERR 0x0d
68 /* response type */
69 #define RSP_R1 0
70 #define RSP_R1b 1
71 #define RSP_R2 2
72 #define RSP_R3 3
73 #define RSP_R4 4
74 #define RSP_R5 5
75 #define RSP_R7 7
77 #define RSP_ERR_CARD_IS_LOCKED (1 << 0)
78 #define RSP_ERR_WP_ERASE_SKIP (1 << 1)
79 #define RSP_ERR_GENERAL (1 << 2)
80 #define RSP_ERR_CC (1 << 3)
81 #define RSP_ERR_ECC (1 << 4)
82 #define RSP_ERR_WP_VIOLATION (1 << 5)
83 #define RSP_ERR_ERASE_PARAM (1 << 6)
84 #define RSP_ERR_OUT_OF_RANGE (1 << 7)
85 #define RSP_ERR_IN_IDLE (1 << 8)
86 #define RSP_ERR_ERASE_RESET (1 << 9)
87 #define RSP_ERR_ILLEGAL_COMMAND (1 << 10)
88 #define RSP_ERR_COM_CRC (1 << 11)
89 #define RSP_ERR_ERASE_SEQUENCE (1 << 12)
90 #define RSP_ERR_ADDRESS (1 << 13)
91 #define RSP_ERR_PARAMETER (1 << 14)
93 #define BLOCK_SIZE 512
95 static unsigned long long extract_bits(uint8_t *buff,
96 int width, int start, int end)
98 unsigned long long r = 0;
99 for (int i = end; i >= start; i--) {
100 int bitpos = width - i - 1;
101 int b = bitpos / 8;
102 int shift = 7 - bitpos % 8;
103 r = (r << 1) | ((buff[b] >> shift) & 1);
105 return r;
108 static void spi_sdcard_enable_cs(const struct spi_sdcard *card)
110 spi_claim_bus(&card->slave);
113 static void spi_sdcard_disable_cs(const struct spi_sdcard *card)
115 spi_release_bus(&card->slave);
118 static void spi_sdcard_sendbyte(const struct spi_sdcard *card, uint8_t b)
120 dprintk("sdcard -> %#x\n", b);
121 spi_xfer(&card->slave, &b, 1, NULL, 0);
124 static uint8_t spi_sdcard_recvbyte(const struct spi_sdcard *card)
126 uint8_t b, t = 0xff;
127 spi_xfer(&card->slave, &t, 1, &b, 1);
128 dprintk("sdcard <- %#x\n", b);
129 return b;
132 static uint8_t spi_sdcard_calculate_command_crc(uint8_t cmd, uint32_t argument)
134 uint8_t crc = 0;
135 crc = crc7_byte(crc, (cmd | 0x40) & 0x7f);
136 crc = crc7_byte(crc, (argument >> (3 * 8)) & 0xff);
137 crc = crc7_byte(crc, (argument >> (2 * 8)) & 0xff);
138 crc = crc7_byte(crc, (argument >> (1 * 8)) & 0xff);
139 crc = crc7_byte(crc, (argument >> (0 * 8)) & 0xff);
140 return crc | 1;
143 static int lookup_cmd_response_type(uint8_t cmd)
145 switch (cmd) {
146 case GO_IDLE_STATE:
147 case SEND_OP_COND:
148 case SWITCH_FUNC:
149 case SEND_CSD:
150 case SEND_CID:
151 case SET_BLOCKLEN:
152 case READ_SINGLE_BLOCK:
153 case READ_MULTIPLEBLOCK:
154 case WRITE_BLOCK:
155 case WRITE_MULTIPLEBLOCK:
156 case PROGRAM_CSD:
157 case SEND_WRITE_PROT:
158 case ERASE_WR_BLK_START_ADDR:
159 case ERASE_WR_BLK_END_ADDR:
160 case LOCK_UNLOCK:
161 case APP_CMD:
162 case GEN_CMD:
163 case CRC_ON_OFF:
164 return RSP_R1;
165 case STOP_TRANSMISSION:
166 case SET_WRITE_PROT:
167 case CLR_WRITE_PROT:
168 case ERASE:
169 return RSP_R1b;
170 case SEND_STATUS:
171 return RSP_R2;
172 case READ_OCR:
173 return RSP_R3;
174 case SEND_IF_COND:
175 return RSP_R7;
177 return -1;
180 static int lookup_acmd_response_type(uint8_t cmd)
182 switch (cmd) {
183 case SEND_NUM_WR_BLOCKS:
184 case SET_WR_BLK_ERASE_COUNT:
185 case SD_SEND_OP_COND:
186 case SET_CLR_CARD_DETECT:
187 case SEND_SCR:
188 return RSP_R1;
189 case SD_STATUS:
190 return RSP_R2;
192 return -1;
195 static int lookup_response_length(int response_type)
197 switch (response_type) {
198 case RSP_R1:
199 case RSP_R1b:
200 return 1;
201 case RSP_R2:
202 return 2;
203 case RSP_R3:
204 case RSP_R7:
205 return 5;
207 return -1;
210 static int response_resolve(int response_type, uint8_t *response,
211 uint32_t *out_register)
213 __maybe_unused static const char * const sd_err[] = {
214 "Card is locked",
215 "wp erase skip | lock/unlok cmd failed",
216 "error",
217 "CC error",
218 "card err failed",
219 "wp violation",
220 "erase param",
221 "out of range | csd overwrite",
222 "in idle state",
223 "erase reset",
224 "illegal command",
225 "com crc error",
226 "erase sequence error",
227 "address error",
228 "parameter error"
230 uint8_t r1 = 0, r2 = 0;
232 if ((response_type == RSP_R1)
233 || (response_type == RSP_R1b)
234 || (response_type == RSP_R2)
235 || (response_type == RSP_R3)
236 || (response_type == RSP_R7))
237 r1 = response[0];
239 if (response_type == RSP_R2)
240 r2 = response[1];
242 if (((response_type == RSP_R3) || (response_type == RSP_R7))
243 && (out_register != NULL)) {
244 *out_register = 0;
245 *out_register = (*out_register << 8) | response[1];
246 *out_register = (*out_register << 8) | response[2];
247 *out_register = (*out_register << 8) | response[3];
248 *out_register = (*out_register << 8) | response[4];
251 if (r1 != 0 || r2 != 0) {
252 int i = 0;
253 uint16_t r = (r1 << 8) | r2;
254 while (r) {
255 if (r & 1)
256 dprintk("SDCARD ERROR: %s\n", sd_err[i]);
257 r = r >> 1;
258 i++;
260 return (r1 << 8) | r2;
263 return 0;
266 static int spi_sdcard_do_command_help(const struct spi_sdcard *card,
267 int is_acmd,
268 uint8_t cmd,
269 uint32_t argument,
270 uint32_t *out_register)
272 int ret, type, length, wait;
273 uint8_t crc, c, response[5];
275 /* calculate crc for command */
276 crc = spi_sdcard_calculate_command_crc(cmd, argument);
278 if (is_acmd)
279 dprintk("\nsdcard execute acmd%d, argument = %#x, crc = %#x\n",
280 cmd, argument, crc);
281 else
282 dprintk("\nsdcard execute cmd%d, argument = %#x, crc = %#x\n",
283 cmd, argument, crc);
285 /* lookup response type of command */
286 if (!is_acmd)
287 type = lookup_cmd_response_type(cmd);
288 else
289 type = lookup_acmd_response_type(cmd);
291 /* lookup response length of command */
292 length = lookup_response_length(type);
294 /* enable cs */
295 spi_sdcard_enable_cs(card);
297 /* just delay 8 clocks */
298 spi_sdcard_recvbyte(card);
300 /* send command */
301 spi_sdcard_sendbyte(card, (cmd | 0x40) & 0x7f);
302 /* send argument */
303 spi_sdcard_sendbyte(card, (argument >> (8 * 3)) & 0xff);
304 spi_sdcard_sendbyte(card, (argument >> (8 * 2)) & 0xff);
305 spi_sdcard_sendbyte(card, (argument >> (8 * 1)) & 0xff);
306 spi_sdcard_sendbyte(card, (argument >> (8 * 0)) & 0xff);
307 /* send crc */
308 spi_sdcard_sendbyte(card, crc);
310 /* waitting for response */
311 wait = 0xffff;
312 while (((c = spi_sdcard_recvbyte(card)) & 0x80) && --wait)
314 if (!wait) {
315 spi_sdcard_disable_cs(card);
316 return -1; /* timeout */
319 /* obtain response */
320 for (int i = 0; i < length; i++) {
321 response[i] = c;
322 c = spi_sdcard_recvbyte(card);
325 if (type == RSP_R1b) {
326 /* waitting done */
327 wait = 0xffffff;
328 while (c == 0 && --wait)
329 c = spi_sdcard_recvbyte(card);
330 if (!wait) {
331 spi_sdcard_disable_cs(card);
332 return -1; /* timeout */
336 spi_sdcard_disable_cs(card);
338 ret = response_resolve(type, response, out_register);
340 return ret;
343 static int spi_sdcard_do_command(const struct spi_sdcard *card,
344 uint8_t cmd,
345 uint32_t argument,
346 uint32_t *out_register)
348 return spi_sdcard_do_command_help(card, 0, cmd, argument, out_register);
351 static int spi_sdcard_do_app_command(const struct spi_sdcard *card,
352 uint8_t cmd,
353 uint32_t argument,
354 uint32_t *out_register)
356 /* CMD55 */
357 if (spi_sdcard_do_command(card, APP_CMD, 0, NULL))
358 return -1;
360 return spi_sdcard_do_command_help(card, 1, cmd, argument, out_register);
363 size_t spi_sdcard_size(const struct spi_sdcard *card)
365 int wait;
366 uint8_t csd[16];
367 uint16_t c = 0;
369 /* CMD9, send csd (128bits register) */
370 if (spi_sdcard_do_command(card, SEND_CSD, 0, NULL))
371 return -1;
373 /* enable CS */
374 spi_sdcard_enable_cs(card);
376 /* waitting start block token */
377 wait = 0xffff;
378 while ((spi_sdcard_recvbyte(card) != CT_BLOCK_START) && --wait)
380 if (!wait) {
381 spi_sdcard_disable_cs(card);
382 return -1;
385 /* receive data */
386 for (int i = 0; i < 16; i++) {
387 csd[i] = spi_sdcard_recvbyte(card);
388 c = crc16_byte(c, csd[i]);
391 /* receive crc and verify check sum */
392 if (((c >> 8) & 0xff) != spi_sdcard_recvbyte(card)) {
393 spi_sdcard_disable_cs(card);
394 return -1;
396 if (((c >> 0) & 0xff) != spi_sdcard_recvbyte(card)) {
397 spi_sdcard_disable_cs(card);
398 return -1;
401 /* disable cs */
402 spi_sdcard_disable_cs(card);
404 if (extract_bits(csd, 128, 126, 127) == 0) {
405 /* csd version 1.0 */
406 size_t c_size = extract_bits(csd, 128, 62, 73);
407 size_t mult = extract_bits(csd, 128, 47, 49);
408 size_t read_bl_len = extract_bits(csd, 128, 80, 83);
409 return (c_size + 1) * mult * (1 << read_bl_len);
412 if (extract_bits(csd, 128, 126, 127) == 1) {
413 /* csd version 2.0 */
414 size_t c_size = extract_bits(csd, 128, 48, 69);
415 return (c_size + 1) * 512 * 1024;
418 return -1;
421 int spi_sdcard_init(struct spi_sdcard *card,
422 const unsigned int bus, const unsigned int cs)
424 int resolve, wait;
425 uint32_t ocr;
427 /* initialize spi controller */
428 spi_setup_slave(bus, cs, &card->slave);
430 /* must wait at least 74 clock ticks after reset
431 * disable cs pin to enter spi mode */
432 spi_sdcard_disable_cs(card);
433 for (int i = 0; i < 10; i++)
434 spi_sdcard_sendbyte(card, 0xff);
436 /* CMD0, reset sdcard */
437 wait = 0xffff;
438 while ((spi_sdcard_do_command(card, GO_IDLE_STATE, 0, NULL)
439 != RSP_ERR_IN_IDLE) && --wait)
441 if (!wait)
442 return -1; /* timeout */
444 /* CMD8 */
445 resolve = spi_sdcard_do_command(card, SEND_IF_COND, 0x1aa, NULL);
446 if (resolve & RSP_ERR_ILLEGAL_COMMAND) {
447 /* ACMD41, initialize card */
448 wait = 0xffff;
449 while ((resolve = spi_sdcard_do_app_command(card,
450 SD_SEND_OP_COND, 0, NULL)) && --wait)
452 if ((resolve & RSP_ERR_ILLEGAL_COMMAND) || !wait) {
453 wait = 0xffff;
454 /* CMD1, initialize card for 2.1mm SD Memory Card */
455 while (spi_sdcard_do_app_command(card, SEND_OP_COND,
456 0, NULL) && --wait)
458 if (!wait)
459 return -1; /* unknown card */
461 } else {
462 /* ACMD41, initialize card */
463 wait = 0xffff;
464 while (spi_sdcard_do_app_command(card, SD_SEND_OP_COND,
465 0x40000000, NULL) && --wait)
467 if (!wait)
468 return -1;
471 /* CMD58, read ocr register */
472 if (spi_sdcard_do_command(card, READ_OCR, 0, &ocr))
473 return -1;
475 /* CMD16, set block length to 512 bytes */
476 if (spi_sdcard_do_command(card, SET_BLOCKLEN, 512, NULL))
477 return -1;
479 /* CCS is bit30 of ocr register
480 * CCS = 0 -> SDSC
481 * CCS = 1 -> SDHC/SDXC
482 * */
483 if ((ocr & 0x40000000) == 0)
484 card->type = SDCARD_TYPE_SDSC;
485 else {
486 /* size > 32G -> SDXC */
487 if (spi_sdcard_size(card) > 32LL * 1024 * 1024 * 1024)
488 card->type = SDCARD_TYPE_SDXC;
489 else
490 card->type = SDCARD_TYPE_SDHC;
493 return 0;
496 int spi_sdcard_single_read(const struct spi_sdcard *card,
497 size_t block_address,
498 void *buff)
500 int wait;
501 uint16_t c = 0;
503 if (card->type == SDCARD_TYPE_SDSC)
504 block_address = block_address * 512;
506 /* CMD17, start single block read */
507 if (spi_sdcard_do_command(card, READ_SINGLE_BLOCK, block_address, NULL))
508 return -1;
510 /* enable cs */
511 spi_sdcard_enable_cs(card);
513 /* waitting start block token */
514 wait = 0xffff;
515 while ((spi_sdcard_recvbyte(card) != CT_BLOCK_START) && --wait)
517 if (!wait) { /* timeout */
518 spi_sdcard_disable_cs(card);
519 return -1;
522 /* receive data */
523 for (int i = 0; i < 512; i++) {
524 ((uint8_t *)buff)[i] = spi_sdcard_recvbyte(card);
525 c = crc16_byte(c, ((uint8_t *)buff)[i]);
528 /* receive crc and verify check sum */
529 if (((c >> 8) & 0xff) != spi_sdcard_recvbyte(card)) {
530 spi_sdcard_disable_cs(card);
531 return -1;
533 if (((c >> 0) & 0xff) != spi_sdcard_recvbyte(card)) {
534 spi_sdcard_disable_cs(card);
535 return -1;
538 /* disable cs */
539 spi_sdcard_disable_cs(card);
541 return 0;
544 int spi_sdcard_multiple_read(const struct spi_sdcard *card,
545 size_t start_block_address,
546 size_t end_block_address,
547 void *buff)
549 int wait;
550 int block_num = end_block_address - start_block_address + 1;
551 if (card->type == SDCARD_TYPE_SDSC) {
552 start_block_address = start_block_address * 512;
553 end_block_address = end_block_address * 512;
555 /* CMD18, start multiple block read */
556 if (spi_sdcard_do_command(card,
557 READ_MULTIPLEBLOCK, start_block_address, NULL))
558 return -1;
560 /* enable cs */
561 spi_sdcard_enable_cs(card);
563 for (int i = 0; i < block_num; i++) {
564 uint16_t c = 0;
566 /* waitting start block token */
567 wait = 0xffff;
568 while ((spi_sdcard_recvbyte(card) != CT_BLOCK_START) && --wait)
570 if (!wait) { /* timeout */
571 spi_sdcard_disable_cs(card);
572 return -1;
575 /* receive data */
576 for (int k = 0; k < 512; k++) {
577 uint8_t tmp = spi_sdcard_recvbyte(card);
578 ((uint8_t *)buff)[512 * i + k] = tmp;
579 c = crc16_byte(c, tmp);
582 /* receive crc and verify check sum */
583 if (((c >> 8) & 0xff) != spi_sdcard_recvbyte(card)) {
584 spi_sdcard_disable_cs(card);
585 return -1;
587 if (((c >> 0) & 0xff) != spi_sdcard_recvbyte(card)) {
588 spi_sdcard_disable_cs(card);
589 return -1;
593 /* disable cs */
594 spi_sdcard_disable_cs(card);
596 if (spi_sdcard_do_command(card, STOP_TRANSMISSION, 0, NULL))
597 if (spi_sdcard_do_command(card, SEND_STATUS, 0, NULL))
598 return -1;
600 return 0;
603 int spi_sdcard_read(const struct spi_sdcard *card,
604 void *dest,
605 size_t offset,
606 size_t count)
608 size_t start_block_address = offset / BLOCK_SIZE;
609 size_t end_block_address = (offset + count - 1) / BLOCK_SIZE;
610 size_t has_begin = !!(offset % BLOCK_SIZE);
611 size_t has_end = !!((offset + count) % BLOCK_SIZE);
613 if (start_block_address == end_block_address) {
614 uint8_t tmp[BLOCK_SIZE];
615 size_t o = offset % BLOCK_SIZE;
616 size_t l = count;
617 if (spi_sdcard_single_read(card, start_block_address, tmp))
618 return -1;
619 memcpy(dest, tmp + o, l);
620 return 0;
623 if (has_begin) {
624 uint8_t tmp[BLOCK_SIZE];
625 size_t o = offset % BLOCK_SIZE;
626 size_t l = BLOCK_SIZE - o;
627 if (spi_sdcard_single_read(card, start_block_address, tmp))
628 return -1;
629 memcpy(dest, tmp + o, l);
632 if (start_block_address + has_begin <= end_block_address - has_end) {
633 size_t start_lba = start_block_address + has_begin;
634 size_t end_lba = end_block_address - has_end;
635 size_t o = has_begin ? BLOCK_SIZE - offset % BLOCK_SIZE : 0;
636 if (start_lba < end_lba) {
637 if (spi_sdcard_multiple_read(card, start_lba, end_lba,
638 dest + o))
639 return -1;
640 } else {
641 if (spi_sdcard_single_read(card, start_lba, dest + o))
642 return -1;
646 if (has_end) {
647 uint8_t tmp[BLOCK_SIZE];
648 size_t o = 0;
649 size_t l = (offset + count) % BLOCK_SIZE;
650 if (spi_sdcard_single_read(card, end_block_address, tmp))
651 return -1;
652 memcpy(dest + count - l, tmp + o, l);
655 return 0;
658 int spi_sdcard_single_write(const struct spi_sdcard *card,
659 size_t block_address,
660 void *buff)
662 int wait;
663 uint16_t c = 0;
664 if (card->type == SDCARD_TYPE_SDSC)
665 block_address = block_address * 512;
667 if (spi_sdcard_do_command(card, WRITE_BLOCK, block_address, NULL))
668 return -1;
670 /* eanbele cs */
671 spi_sdcard_enable_cs(card);
673 /* send start block token */
674 spi_sdcard_sendbyte(card, CT_BLOCK_START);
676 /* send data */
677 for (int i = 0; i < 512; i++) {
678 spi_sdcard_sendbyte(card, ((uint8_t *)buff)[i]);
679 c = crc16_byte(c, ((uint8_t *)buff)[i]);
682 /* send crc check sum */
683 spi_sdcard_sendbyte(card, 0xff & (c >> 8));
684 spi_sdcard_sendbyte(card, 0xff & (c >> 0));
686 /* receive and verify data response token */
687 c = spi_sdcard_recvbyte(card);
688 if ((c & CT_RESPONSE_MASK) != CT_RESPONSE_ACCEPTED) {
689 spi_sdcard_disable_cs(card);
690 return -1;
693 wait = 0xffff;
694 while ((spi_sdcard_recvbyte(card) == 0) && --wait)
695 ;/* wait for complete */
696 if (!wait) {
697 spi_sdcard_disable_cs(card);
698 return -1;
701 /* disable cs */
702 spi_sdcard_disable_cs(card);
704 return 0;
707 int spi_sdcard_multiple_write(const struct spi_sdcard *card,
708 size_t start_block_address,
709 size_t end_block_address,
710 void *buff)
712 int wait, ret = 0;
713 int block_num = end_block_address - start_block_address + 1;
714 if (card->type == SDCARD_TYPE_SDSC) {
715 start_block_address = start_block_address * 512;
716 end_block_address = end_block_address * 512;
719 if (spi_sdcard_do_command(card, WRITE_MULTIPLEBLOCK,
720 start_block_address, NULL))
721 return -1;
723 /* enable cs */
724 spi_sdcard_enable_cs(card);
726 for (int i = 0; i < block_num; i++) {
727 uint16_t c = 0;
729 ret = -1;
731 /* send start block token */
732 spi_sdcard_sendbyte(card, CT_MULTIPLE_BLOCK_START);
734 /* send data */
735 for (int k = 0; k < 512; k++) {
736 uint8_t tmp = ((uint8_t *)buff)[512 * i + k];
737 spi_sdcard_sendbyte(card, tmp);
738 c = crc16_byte(c, tmp);
741 /* send crc check sum */
742 spi_sdcard_sendbyte(card, 0xff & (c >> 8));
743 spi_sdcard_sendbyte(card, 0xff & (c >> 0));
745 /* receive and verify data response token */
746 c = spi_sdcard_recvbyte(card);
747 if ((c & CT_RESPONSE_MASK) != CT_RESPONSE_ACCEPTED)
748 break;
750 wait = 0xffff;
751 while ((spi_sdcard_recvbyte(card) == 0) && --wait)
752 ;/* wait for complete */
753 if (!wait)
754 break;
756 ret = 0;
759 /* send stop transmission token */
760 spi_sdcard_sendbyte(card, CT_MULTIPLE_BLOCK_STOP);
762 /* disable cs */
763 spi_sdcard_disable_cs(card);
765 if (spi_sdcard_do_command(card, STOP_TRANSMISSION, 0, NULL))
766 if (spi_sdcard_do_command(card, SEND_STATUS, 0, NULL))
767 return -1;
769 return ret;
772 int spi_sdcard_erase(const struct spi_sdcard *card,
773 size_t start_block_address,
774 size_t end_block_address)
776 if (card->type == SDCARD_TYPE_SDSC) {
777 start_block_address = start_block_address * 512;
778 end_block_address = end_block_address * 512;
781 /* CMD32, set erase start address */
782 if (spi_sdcard_do_command(card, ERASE_WR_BLK_START_ADDR,
783 start_block_address, NULL))
784 return -1;
786 /* CMD33, set erase end address */
787 if (spi_sdcard_do_command(card, ERASE_WR_BLK_END_ADDR,
788 end_block_address, NULL))
789 return -1;
791 /* CMD38, erase */
792 if (spi_sdcard_do_command(card, ERASE, 0, NULL))
793 return -1;
795 return 0;
798 int spi_sdcard_erase_all(const struct spi_sdcard *card)
800 return spi_sdcard_erase(card, 0, spi_sdcard_size(card) / BLOCK_SIZE);