soc/mediatek/mt8196: Initialize SSPM
[coreboot.git] / src / drivers / spi / spi_sdcard.c
blob6a7fbf95cf3a5202728e2b11ecfb1f6c57d5e21e
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 0
12 #define dprintk(fmt, args...) \
13 do { if (SPI_SDCARD_DEBUG) { printk(BIOS_DEBUG, fmt, ##args); }} while (0)
15 #define SDCARD_TYPE_SDSC 1
16 #define SDCARD_TYPE_SDHC 2
17 #define SDCARD_TYPE_SDXC 3
19 /* CMD */
20 #define GO_IDLE_STATE 0
21 #define SEND_OP_COND 1
22 #define SWITCH_FUNC 6
23 #define SEND_IF_COND 8
24 #define SEND_CSD 9
25 #define SEND_CID 10
26 #define STOP_TRANSMISSION 12
27 #define SEND_STATUS 13
28 #define SET_BLOCKLEN 16
29 #define READ_SINGLE_BLOCK 17
30 #define READ_MULTIPLEBLOCK 18
31 #define WRITE_BLOCK 24
32 #define WRITE_MULTIPLEBLOCK 25
33 #define PROGRAM_CSD 27
34 #define SET_WRITE_PROT 28
35 #define CLR_WRITE_PROT 29
36 #define SEND_WRITE_PROT 30
37 #define ERASE_WR_BLK_START_ADDR 32
38 #define ERASE_WR_BLK_END_ADDR 33
39 #define ERASE 38
40 #define LOCK_UNLOCK 42
41 #define APP_CMD 55
42 #define GEN_CMD 56
43 #define READ_OCR 58
44 #define CRC_ON_OFF 59
46 /* ACMD */
47 #define SD_STATUS 13
48 #define SEND_NUM_WR_BLOCKS 22
49 #define SET_WR_BLK_ERASE_COUNT 23
50 #define SD_SEND_OP_COND 41
51 #define SET_CLR_CARD_DETECT 42
52 #define SEND_SCR 51
54 /* control tokens */
55 #define CT_BLOCK_START 0xfe
56 #define CT_MULTIPLE_BLOCK_START 0xfc
57 #define CT_MULTIPLE_BLOCK_STOP 0xfd
58 #define CT_RESPONSE_MASK 0x1f
59 #define CT_RESPONSE_ACCEPTED 0x05
60 #define CT_RESPONSE_REJECTED_CRC 0x0b
61 #define CT_RESPONSE_REJECTED_WRITE_ERR 0x0d
63 /* response type */
64 #define RSP_R1 0
65 #define RSP_R1b 1
66 #define RSP_R2 2
67 #define RSP_R3 3
68 #define RSP_R4 4
69 #define RSP_R5 5
70 #define RSP_R7 7
72 #define RSP_ERR_CARD_IS_LOCKED (1 << 0)
73 #define RSP_ERR_WP_ERASE_SKIP (1 << 1)
74 #define RSP_ERR_GENERAL (1 << 2)
75 #define RSP_ERR_CC (1 << 3)
76 #define RSP_ERR_ECC (1 << 4)
77 #define RSP_ERR_WP_VIOLATION (1 << 5)
78 #define RSP_ERR_ERASE_PARAM (1 << 6)
79 #define RSP_ERR_OUT_OF_RANGE (1 << 7)
80 #define RSP_ERR_IN_IDLE (1 << 8)
81 #define RSP_ERR_ERASE_RESET (1 << 9)
82 #define RSP_ERR_ILLEGAL_COMMAND (1 << 10)
83 #define RSP_ERR_COM_CRC (1 << 11)
84 #define RSP_ERR_ERASE_SEQUENCE (1 << 12)
85 #define RSP_ERR_ADDRESS (1 << 13)
86 #define RSP_ERR_PARAMETER (1 << 14)
88 #define BLOCK_SIZE 512
90 static unsigned long long extract_bits(uint8_t *buff,
91 int width, int start, int end)
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);
100 return r;
103 static void spi_sdcard_enable_cs(const struct spi_sdcard *card)
105 spi_claim_bus(&card->slave);
108 static void spi_sdcard_disable_cs(const struct spi_sdcard *card)
110 spi_release_bus(&card->slave);
113 static void spi_sdcard_sendbyte(const struct spi_sdcard *card, uint8_t b)
115 dprintk("sdcard -> %#x\n", b);
116 spi_xfer(&card->slave, &b, 1, NULL, 0);
119 static uint8_t spi_sdcard_recvbyte(const struct spi_sdcard *card)
121 uint8_t b, t = 0xff;
122 spi_xfer(&card->slave, &t, 1, &b, 1);
123 dprintk("sdcard <- %#x\n", b);
124 return b;
127 static uint8_t spi_sdcard_calculate_command_crc(uint8_t cmd, uint32_t argument)
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;
138 static int lookup_cmd_response_type(uint8_t cmd)
140 switch (cmd) {
141 case GO_IDLE_STATE:
142 case SEND_OP_COND:
143 case SWITCH_FUNC:
144 case SEND_CSD:
145 case SEND_CID:
146 case SET_BLOCKLEN:
147 case READ_SINGLE_BLOCK:
148 case READ_MULTIPLEBLOCK:
149 case WRITE_BLOCK:
150 case WRITE_MULTIPLEBLOCK:
151 case PROGRAM_CSD:
152 case SEND_WRITE_PROT:
153 case ERASE_WR_BLK_START_ADDR:
154 case ERASE_WR_BLK_END_ADDR:
155 case LOCK_UNLOCK:
156 case APP_CMD:
157 case GEN_CMD:
158 case CRC_ON_OFF:
159 return RSP_R1;
160 case STOP_TRANSMISSION:
161 case SET_WRITE_PROT:
162 case CLR_WRITE_PROT:
163 case ERASE:
164 return RSP_R1b;
165 case SEND_STATUS:
166 return RSP_R2;
167 case READ_OCR:
168 return RSP_R3;
169 case SEND_IF_COND:
170 return RSP_R7;
172 return -1;
175 static int lookup_acmd_response_type(uint8_t cmd)
177 switch (cmd) {
178 case SEND_NUM_WR_BLOCKS:
179 case SET_WR_BLK_ERASE_COUNT:
180 case SD_SEND_OP_COND:
181 case SET_CLR_CARD_DETECT:
182 case SEND_SCR:
183 return RSP_R1;
184 case SD_STATUS:
185 return RSP_R2;
187 return -1;
190 static int lookup_response_length(int response_type)
192 switch (response_type) {
193 case RSP_R1:
194 case RSP_R1b:
195 return 1;
196 case RSP_R2:
197 return 2;
198 case RSP_R3:
199 case RSP_R7:
200 return 5;
202 return -1;
205 static int response_resolve(int response_type, uint8_t *response,
206 uint32_t *out_register)
208 __maybe_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"
225 uint8_t r1 = 0, r2 = 0;
227 if ((response_type == RSP_R1)
228 || (response_type == RSP_R1b)
229 || (response_type == RSP_R2)
230 || (response_type == RSP_R3)
231 || (response_type == RSP_R7))
232 r1 = response[0];
234 if (response_type == RSP_R2)
235 r2 = response[1];
237 if (((response_type == RSP_R3) || (response_type == RSP_R7))
238 && (out_register != NULL)) {
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];
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]);
252 r = r >> 1;
253 i++;
255 return (r1 << 8) | r2;
258 return 0;
261 static 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)
267 int ret, type, length, wait;
268 uint8_t crc, c, response[5];
270 /* calculate crc for command */
271 crc = spi_sdcard_calculate_command_crc(cmd, argument);
273 if (is_acmd)
274 dprintk("\nsdcard execute acmd%d, argument = %#x, crc = %#x\n",
275 cmd, argument, crc);
276 else
277 dprintk("\nsdcard execute cmd%d, argument = %#x, crc = %#x\n",
278 cmd, argument, crc);
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);
286 /* lookup response length of command */
287 length = lookup_response_length(type);
289 /* enable cs */
290 spi_sdcard_enable_cs(card);
292 /* just delay 8 clocks */
293 spi_sdcard_recvbyte(card);
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);
305 /* waiting for response */
306 wait = 0xffff;
307 while (((c = spi_sdcard_recvbyte(card)) & 0x80) && --wait)
309 if (!wait) {
310 spi_sdcard_disable_cs(card);
311 return -1; /* timeout */
314 /* obtain response */
315 for (int i = 0; i < length; i++) {
316 response[i] = c;
317 c = spi_sdcard_recvbyte(card);
320 if (type == RSP_R1b) {
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 */
331 spi_sdcard_disable_cs(card);
333 ret = response_resolve(type, response, out_register);
335 return ret;
338 static int spi_sdcard_do_command(const struct spi_sdcard *card,
339 uint8_t cmd,
340 uint32_t argument,
341 uint32_t *out_register)
343 return spi_sdcard_do_command_help(card, 0, cmd, argument, out_register);
346 static int spi_sdcard_do_app_command(const struct spi_sdcard *card,
347 uint8_t cmd,
348 uint32_t argument,
349 uint32_t *out_register)
351 /* CMD55 */
352 if (spi_sdcard_do_command(card, APP_CMD, 0, NULL))
353 return -1;
355 return spi_sdcard_do_command_help(card, 1, cmd, argument, out_register);
358 size_t spi_sdcard_size(const struct spi_sdcard *card)
360 int wait;
361 uint8_t csd[16];
362 uint16_t c = 0;
364 /* CMD9, send csd (128bits register) */
365 if (spi_sdcard_do_command(card, SEND_CSD, 0, NULL))
366 return -1;
368 /* enable CS */
369 spi_sdcard_enable_cs(card);
371 /* waiting start block token */
372 wait = 0xffff;
373 while ((spi_sdcard_recvbyte(card) != CT_BLOCK_START) && --wait)
375 if (!wait) {
376 spi_sdcard_disable_cs(card);
377 return -1;
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]);
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;
391 if (((c >> 0) & 0xff) != spi_sdcard_recvbyte(card)) {
392 spi_sdcard_disable_cs(card);
393 return -1;
396 /* disable cs */
397 spi_sdcard_disable_cs(card);
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);
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;
413 return -1;
416 int spi_sdcard_init(struct spi_sdcard *card,
417 const unsigned int bus, const unsigned int cs)
419 int resolve, wait;
420 uint32_t ocr;
422 /* initialize spi controller */
423 spi_setup_slave(bus, cs, &card->slave);
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);
431 /* CMD0, reset sdcard */
432 wait = 0xffff;
433 while ((spi_sdcard_do_command(card, GO_IDLE_STATE, 0, NULL)
434 != RSP_ERR_IN_IDLE) && --wait)
436 if (!wait)
437 return -1; /* timeout */
439 /* CMD8 */
440 resolve = spi_sdcard_do_command(card, SEND_IF_COND, 0x1aa, NULL);
441 if (resolve & RSP_ERR_ILLEGAL_COMMAND) {
442 /* ACMD41, initialize card */
443 wait = 0xffff;
444 while ((resolve = spi_sdcard_do_app_command(card,
445 SD_SEND_OP_COND, 0, NULL)) && --wait)
447 if ((resolve & RSP_ERR_ILLEGAL_COMMAND) || !wait) {
448 wait = 0xffff;
449 /* CMD1, initialize card for 2.1mm SD Memory Card */
450 while (spi_sdcard_do_app_command(card, SEND_OP_COND,
451 0, NULL) && --wait)
453 if (!wait)
454 return -1; /* unknown card */
456 } else {
457 /* ACMD41, initialize card */
458 wait = 0xffff;
459 while (spi_sdcard_do_app_command(card, SD_SEND_OP_COND,
460 0x40000000, NULL) && --wait)
462 if (!wait)
463 return -1;
466 /* CMD58, read ocr register */
467 if (spi_sdcard_do_command(card, READ_OCR, 0, &ocr))
468 return -1;
470 /* CMD16, set block length to 512 bytes */
471 if (spi_sdcard_do_command(card, SET_BLOCKLEN, 512, NULL))
472 return -1;
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_SDSC;
480 else {
481 /* size > 32G -> SDXC */
482 if (spi_sdcard_size(card) > 32LL * 1024 * 1024 * 1024)
483 card->type = SDCARD_TYPE_SDXC;
484 else
485 card->type = SDCARD_TYPE_SDHC;
488 return 0;
491 int spi_sdcard_single_read(const struct spi_sdcard *card,
492 size_t block_address,
493 void *buff)
495 int wait;
496 uint16_t c = 0;
498 if (card->type == SDCARD_TYPE_SDSC)
499 block_address = block_address * 512;
501 /* CMD17, start single block read */
502 if (spi_sdcard_do_command(card, READ_SINGLE_BLOCK, block_address, NULL))
503 return -1;
505 /* enable cs */
506 spi_sdcard_enable_cs(card);
508 /* waiting start block token */
509 wait = 0xffff;
510 while ((spi_sdcard_recvbyte(card) != CT_BLOCK_START) && --wait)
512 if (!wait) { /* timeout */
513 spi_sdcard_disable_cs(card);
514 return -1;
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]);
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;
528 if (((c >> 0) & 0xff) != spi_sdcard_recvbyte(card)) {
529 spi_sdcard_disable_cs(card);
530 return -1;
533 /* disable cs */
534 spi_sdcard_disable_cs(card);
536 return 0;
539 int spi_sdcard_multiple_read(const struct spi_sdcard *card,
540 size_t start_block_address,
541 size_t end_block_address,
542 void *buff)
544 int wait;
545 int block_num = end_block_address - start_block_address + 1;
546 if (card->type == SDCARD_TYPE_SDSC) {
547 start_block_address = start_block_address * 512;
548 end_block_address = end_block_address * 512;
550 /* CMD18, start multiple block read */
551 if (spi_sdcard_do_command(card,
552 READ_MULTIPLEBLOCK, start_block_address, NULL))
553 return -1;
555 /* enable cs */
556 spi_sdcard_enable_cs(card);
558 for (int i = 0; i < block_num; i++) {
559 uint16_t c = 0;
561 /* waiting start block token */
562 wait = 0xffff;
563 while ((spi_sdcard_recvbyte(card) != CT_BLOCK_START) && --wait)
565 if (!wait) { /* timeout */
566 spi_sdcard_disable_cs(card);
567 return -1;
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);
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;
582 if (((c >> 0) & 0xff) != spi_sdcard_recvbyte(card)) {
583 spi_sdcard_disable_cs(card);
584 return -1;
588 /* disable cs */
589 spi_sdcard_disable_cs(card);
591 if (spi_sdcard_do_command(card, STOP_TRANSMISSION, 0, NULL))
592 if (spi_sdcard_do_command(card, SEND_STATUS, 0, NULL))
593 return -1;
595 return 0;
598 int spi_sdcard_read(const struct spi_sdcard *card,
599 void *dest,
600 size_t offset,
601 size_t count)
603 size_t start_block_address = offset / BLOCK_SIZE;
604 size_t end_block_address = (offset + count - 1) / BLOCK_SIZE;
605 size_t has_begin = !!(offset % BLOCK_SIZE);
606 size_t has_end = !!((offset + count) % BLOCK_SIZE);
608 if (start_block_address == end_block_address) {
609 uint8_t tmp[BLOCK_SIZE];
610 size_t o = offset % BLOCK_SIZE;
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;
618 if (has_begin) {
619 uint8_t tmp[BLOCK_SIZE];
620 size_t o = offset % BLOCK_SIZE;
621 size_t l = BLOCK_SIZE - o;
622 if (spi_sdcard_single_read(card, start_block_address, tmp))
623 return -1;
624 memcpy(dest, tmp + o, l);
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_SIZE - offset % BLOCK_SIZE : 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;
641 if (has_end) {
642 uint8_t tmp[BLOCK_SIZE];
643 size_t o = 0;
644 size_t l = (offset + count) % BLOCK_SIZE;
645 if (spi_sdcard_single_read(card, end_block_address, tmp))
646 return -1;
647 memcpy(dest + count - l, tmp + o, l);
650 return 0;
653 int spi_sdcard_single_write(const struct spi_sdcard *card,
654 size_t block_address,
655 void *buff)
657 int wait;
658 uint16_t c = 0;
659 if (card->type == SDCARD_TYPE_SDSC)
660 block_address = block_address * 512;
662 if (spi_sdcard_do_command(card, WRITE_BLOCK, block_address, NULL))
663 return -1;
665 /* enable cs */
666 spi_sdcard_enable_cs(card);
668 /* send start block token */
669 spi_sdcard_sendbyte(card, CT_BLOCK_START);
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]);
677 /* send crc check sum */
678 spi_sdcard_sendbyte(card, 0xff & (c >> 8));
679 spi_sdcard_sendbyte(card, 0xff & (c >> 0));
681 /* receive and verify data response token */
682 c = spi_sdcard_recvbyte(card);
683 if ((c & CT_RESPONSE_MASK) != CT_RESPONSE_ACCEPTED) {
684 spi_sdcard_disable_cs(card);
685 return -1;
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;
696 /* disable cs */
697 spi_sdcard_disable_cs(card);
699 return 0;
702 int spi_sdcard_multiple_write(const struct spi_sdcard *card,
703 size_t start_block_address,
704 size_t end_block_address,
705 void *buff)
707 int wait, ret = 0;
708 int block_num = end_block_address - start_block_address + 1;
709 if (card->type == SDCARD_TYPE_SDSC) {
710 start_block_address = start_block_address * 512;
711 end_block_address = end_block_address * 512;
714 if (spi_sdcard_do_command(card, WRITE_MULTIPLEBLOCK,
715 start_block_address, NULL))
716 return -1;
718 /* enable cs */
719 spi_sdcard_enable_cs(card);
721 for (int i = 0; i < block_num; i++) {
722 uint16_t c = 0;
724 ret = -1;
726 /* send start block token */
727 spi_sdcard_sendbyte(card, CT_MULTIPLE_BLOCK_START);
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);
736 /* send crc check sum */
737 spi_sdcard_sendbyte(card, 0xff & (c >> 8));
738 spi_sdcard_sendbyte(card, 0xff & (c >> 0));
740 /* receive and verify data response token */
741 c = spi_sdcard_recvbyte(card);
742 if ((c & CT_RESPONSE_MASK) != CT_RESPONSE_ACCEPTED)
743 break;
745 wait = 0xffff;
746 while ((spi_sdcard_recvbyte(card) == 0) && --wait)
747 ;/* wait for complete */
748 if (!wait)
749 break;
751 ret = 0;
754 /* send stop transmission token */
755 spi_sdcard_sendbyte(card, CT_MULTIPLE_BLOCK_STOP);
757 /* disable cs */
758 spi_sdcard_disable_cs(card);
760 if (spi_sdcard_do_command(card, STOP_TRANSMISSION, 0, NULL))
761 if (spi_sdcard_do_command(card, SEND_STATUS, 0, NULL))
762 return -1;
764 return ret;
767 int spi_sdcard_erase(const struct spi_sdcard *card,
768 size_t start_block_address,
769 size_t end_block_address)
771 if (card->type == SDCARD_TYPE_SDSC) {
772 start_block_address = start_block_address * 512;
773 end_block_address = end_block_address * 512;
776 /* CMD32, set erase start address */
777 if (spi_sdcard_do_command(card, ERASE_WR_BLK_START_ADDR,
778 start_block_address, NULL))
779 return -1;
781 /* CMD33, set erase end address */
782 if (spi_sdcard_do_command(card, ERASE_WR_BLK_END_ADDR,
783 end_block_address, NULL))
784 return -1;
786 /* CMD38, erase */
787 if (spi_sdcard_do_command(card, ERASE, 0, NULL))
788 return -1;
790 return 0;
793 int spi_sdcard_erase_all(const struct spi_sdcard *card)
795 return spi_sdcard_erase(card, 0, spi_sdcard_size(card) / BLOCK_SIZE);