xref: /aosp_15_r20/external/coreboot/src/drivers/spi/spi_sdcard.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
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_DEBUG 0
11 
12 #define dprintk(fmt, args...) \
13 	do { if (SPI_SDCARD_DEBUG) { printk(BIOS_DEBUG, fmt, ##args); }} while (0)
14 
15 #define SDCARD_TYPE_SDSC	1
16 #define SDCARD_TYPE_SDHC	2
17 #define SDCARD_TYPE_SDXC	3
18 
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
45 
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
53 
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
62 
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
71 
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)
87 
88 #define BLOCK_SIZE	512
89 
extract_bits(uint8_t * buff,int width,int start,int end)90 static 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 
spi_sdcard_enable_cs(const struct spi_sdcard * card)103 static void spi_sdcard_enable_cs(const struct spi_sdcard *card)
104 {
105 	spi_claim_bus(&card->slave);
106 }
107 
spi_sdcard_disable_cs(const struct spi_sdcard * card)108 static void spi_sdcard_disable_cs(const struct spi_sdcard *card)
109 {
110 	spi_release_bus(&card->slave);
111 }
112 
spi_sdcard_sendbyte(const struct spi_sdcard * card,uint8_t b)113 static void spi_sdcard_sendbyte(const struct spi_sdcard *card, uint8_t b)
114 {
115 	dprintk("sdcard -> %#x\n", b);
116 	spi_xfer(&card->slave, &b, 1, NULL, 0);
117 }
118 
spi_sdcard_recvbyte(const struct spi_sdcard * card)119 static 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);
124 	return b;
125 }
126 
spi_sdcard_calculate_command_crc(uint8_t cmd,uint32_t argument)127 static 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 
lookup_cmd_response_type(uint8_t cmd)138 static int lookup_cmd_response_type(uint8_t cmd)
139 {
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;
171 	}
172 	return -1;
173 }
174 
lookup_acmd_response_type(uint8_t cmd)175 static int lookup_acmd_response_type(uint8_t cmd)
176 {
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;
186 	}
187 	return -1;
188 }
189 
lookup_response_length(int response_type)190 static int lookup_response_length(int response_type)
191 {
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;
201 	}
202 	return -1;
203 }
204 
response_resolve(int response_type,uint8_t * response,uint32_t * out_register)205 static int response_resolve(int response_type, uint8_t *response,
206 	uint32_t *out_register)
207 {
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"
224 	};
225 	uint8_t r1 = 0, r2 = 0;
226 
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];
233 
234 	if (response_type == RSP_R2)
235 		r2 = response[1];
236 
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];
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]);
252 			r = r >> 1;
253 			i++;
254 		}
255 		return (r1 << 8) | r2;
256 	}
257 
258 	return 0;
259 }
260 
spi_sdcard_do_command_help(const struct spi_sdcard * card,int is_acmd,uint8_t cmd,uint32_t argument,uint32_t * out_register)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)
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",
275 				cmd, argument, crc);
276 	else
277 		dprintk("\nsdcard execute  cmd%d, argument = %#x, crc = %#x\n",
278 				cmd, argument, crc);
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_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 */
328 		}
329 	}
330 
331 	spi_sdcard_disable_cs(card);
332 
333 	ret = response_resolve(type, response, out_register);
334 
335 	return ret;
336 }
337 
spi_sdcard_do_command(const struct spi_sdcard * card,uint8_t cmd,uint32_t argument,uint32_t * out_register)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)
342 {
343 	return spi_sdcard_do_command_help(card, 0, cmd, argument, out_register);
344 }
345 
spi_sdcard_do_app_command(const struct spi_sdcard * card,uint8_t cmd,uint32_t argument,uint32_t * 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)
350 {
351 	/* CMD55 */
352 	if (spi_sdcard_do_command(card, APP_CMD, 0, NULL))
353 		return -1;
354 
355 	return spi_sdcard_do_command_help(card, 1, cmd, argument, out_register);
356 }
357 
spi_sdcard_size(const struct spi_sdcard * card)358 size_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_CSD, 0, NULL))
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_START) && --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 
spi_sdcard_init(struct spi_sdcard * card,const unsigned int bus,const unsigned int cs)416 int 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_STATE, 0, NULL)
434 			!= RSP_ERR_IN_IDLE) && --wait)
435 		;
436 	if (!wait)
437 		return -1; /* timeout */
438 
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)
446 			;
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)
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_COND,
460 				0x40000000, NULL) && --wait)
461 			;
462 		if (!wait)
463 			return -1;
464 	}
465 
466 	/* CMD58, read ocr register */
467 	if (spi_sdcard_do_command(card, READ_OCR, 0, &ocr))
468 		return -1;
469 
470 	/* CMD16, set block length to 512 bytes */
471 	if (spi_sdcard_do_command(card, SET_BLOCKLEN, 512, NULL))
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_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;
486 	}
487 
488 	return 0;
489 }
490 
spi_sdcard_single_read(const struct spi_sdcard * card,size_t block_address,void * buff)491 int 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_SDSC)
499 		block_address = block_address * 512;
500 
501 	/* CMD17, start single block read */
502 	if (spi_sdcard_do_command(card, READ_SINGLE_BLOCK, block_address, NULL))
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_START) && --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 
spi_sdcard_multiple_read(const struct spi_sdcard * card,size_t start_block_address,size_t end_block_address,void * buff)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)
543 {
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;
549 	}
550 	/* CMD18, start multiple block read */
551 	if (spi_sdcard_do_command(card,
552 			READ_MULTIPLEBLOCK, start_block_address, NULL))
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_START) && --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_TRANSMISSION, 0, NULL))
592 		if (spi_sdcard_do_command(card, SEND_STATUS, 0, NULL))
593 			return -1;
594 
595 	return 0;
596 }
597 
spi_sdcard_read(const struct spi_sdcard * card,void * dest,size_t offset,size_t count)598 int 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_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);
607 
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;
616 	}
617 
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);
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_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;
638 		}
639 	}
640 
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);
648 	}
649 
650 	return 0;
651 }
652 
spi_sdcard_single_write(const struct spi_sdcard * card,size_t block_address,void * buff)653 int 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_SDSC)
660 		block_address = block_address * 512;
661 
662 	if (spi_sdcard_do_command(card, WRITE_BLOCK, block_address, NULL))
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_START);
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_MASK) != CT_RESPONSE_ACCEPTED) {
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 
spi_sdcard_multiple_write(const struct spi_sdcard * card,size_t start_block_address,size_t end_block_address,void * buff)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)
706 {
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;
712 	}
713 
714 	if (spi_sdcard_do_command(card, WRITE_MULTIPLEBLOCK,
715 		start_block_address, NULL))
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_START);
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_MASK) != CT_RESPONSE_ACCEPTED)
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_STOP);
756 
757 	/* disable cs */
758 	spi_sdcard_disable_cs(card);
759 
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;
763 
764 	return ret;
765 }
766 
spi_sdcard_erase(const struct spi_sdcard * card,size_t start_block_address,size_t end_block_address)767 int 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_SDSC) {
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_ADDR,
778 			start_block_address, NULL))
779 		return -1;
780 
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;
785 
786 	/* CMD38, erase */
787 	if (spi_sdcard_do_command(card, ERASE, 0, NULL))
788 		return -1;
789 
790 	return 0;
791 }
792 
spi_sdcard_erase_all(const struct spi_sdcard * card)793 int spi_sdcard_erase_all(const struct spi_sdcard *card)
794 {
795 	return spi_sdcard_erase(card, 0, spi_sdcard_size(card) / BLOCK_SIZE);
796 }
797