1 /*
2 * Copyright (c) 2021-2023 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include "hpm_sdmmc_sd.h"
9 #include "hpm_l1c_drv.h"
10
11 #define SPEED_1Kbps (1000U)
12 #define SPEED_1Mbps (1000UL * 1000UL)
13 #define MAX_BLOCK_COUNT ((1UL << 26) / 512 - 1U)
14 #define WRITE_BLOCK_TIMEOUT_IN_MS (1000U)
15 #define READ_BLOCK_TIMEOUT_IN_MS (100U)
16
17 typedef union {
18 uint32_t status_words[16];
19 struct {
20 uint32_t reserved[12];
21 uint64_t : 8;
22 uint64_t uhs_au_size: 4;
23 uint64_t uhs_speed_grade: 4;
24 uint64_t erase_offset: 2;
25 uint64_t erase_timeout: 6;
26 uint64_t erase_size: 16;
27 uint64_t : 4;
28 uint64_t au_size: 4;
29 uint64_t performance_move: 8;
30 uint64_t speed_class: 8;
31
32 uint32_t size_of_protected_area;
33
34 uint32_t sd_card_type: 16;
35 uint32_t : 6;
36 uint32_t : 7;
37 uint32_t secured_mode: 1;
38 uint32_t data_bus_width: 2;
39 };
40 } sd_raw_status_t;
41
42 static uint32_t sd_be2le(uint32_t be);
43
44 static void sd_convert_data_endian(uint32_t *word, uint32_t word_count);
45
46 static hpm_stat_t sd_send_card_status(sd_card_t *card);
47
48 static hpm_stat_t sd_send_rca(sd_card_t *card);
49
50 static hpm_stat_t sd_send_csd(sd_card_t *card);
51
52 static hpm_stat_t sd_switch_function(sd_card_t *card, uint32_t mode, uint32_t group, uint32_t number);
53
54 static void sd_decode_scr(sd_card_t *card, uint32_t *raw_scr);
55
56 static hpm_stat_t sd_send_scr(sd_card_t *card);
57
58 static hpm_stat_t sd_app_cmd_send_cond_op(sd_card_t *card, sd_ocr_t ocr);
59
60 static hpm_stat_t sd_send_if_cond(sd_card_t *card);
61
62 static hpm_stat_t sd_probe_bus_voltage(sd_card_t *card);
63
64 static hpm_stat_t sd_switch_voltage(sd_card_t *card);
65
66 static void sd_decode_csd(sd_card_t *card, uint32_t *raw_csd);
67
68 static void sd_decode_status(sd_card_t *card, uint32_t *raw_status);
69
70 static hpm_stat_t sd_set_bus_width(sd_card_t *card, sdmmc_buswidth_t buswidth);
71
72 static hpm_stat_t sd_set_bus_timing(sd_card_t *card, sdmmc_speed_mode_t timing_mode);
73
74 static hpm_stat_t sd_check_card_parameters(sd_card_t *card);
75
76 static hpm_stat_t sd_app_cmd_set_write_block_erase_count(sd_card_t *card, uint32_t block_count);
77
78 static hpm_stat_t sd_error_recovery(sd_card_t *card);
79
80 static hpm_stat_t sd_send_cmd(sd_card_t *card, sdmmchost_cmd_t *cmd);
81
82 static hpm_stat_t sd_transfer(sd_card_t *card, sdmmchost_xfer_t *content);
83
sd_send_cmd(sd_card_t * card,sdmmchost_cmd_t * cmd)84 static hpm_stat_t sd_send_cmd(sd_card_t *card, sdmmchost_cmd_t *cmd)
85 {
86 hpm_stat_t status = sdmmchost_send_command(card->host, cmd);
87
88 if ((status >= status_sdxc_busy) && (status <= status_sdxc_tuning_failed)) {
89 hpm_stat_t error_recovery_status = sd_error_recovery(card);
90 if (error_recovery_status != status_success) {
91 status = error_recovery_status;
92 }
93 }
94 return status;
95 }
96
sd_transfer(sd_card_t * card,sdmmchost_xfer_t * content)97 static hpm_stat_t sd_transfer(sd_card_t *card, sdmmchost_xfer_t *content)
98 {
99 hpm_stat_t status = sdmmchost_transfer(card->host, content);
100
101 if ((status >= status_sdxc_busy) && (status <= status_sdxc_tuning_failed)) {
102 hpm_stat_t error_recovery_status = sd_error_recovery(card);
103 if (error_recovery_status != status_success) {
104 status = error_recovery_status;
105 }
106 }
107 return status;
108 }
109
sd_convert_data_endian(uint32_t * word,uint32_t word_count)110 static void sd_convert_data_endian(uint32_t *word, uint32_t word_count)
111 {
112 for (uint32_t i = 0; i < word_count / 2; i++) {
113 uint32_t temp = word[i];
114 word[i] = word[word_count - i - 1];
115 word[word_count - i - 1] = temp;
116 }
117
118 for (uint32_t i = 0; i < word_count; i++) {
119 word[i] = sd_be2le(word[i]);
120 }
121 }
122
sd_send_card_status(sd_card_t * card)123 static hpm_stat_t sd_send_card_status(sd_card_t *card)
124 {
125 hpm_stat_t status;
126
127 sdmmchost_cmd_t *cmd = &card->host->cmd;
128 memset(cmd, 0, sizeof(*cmd));
129 cmd->cmd_index = sdmmc_cmd_send_status;
130 cmd->resp_type = (sdxc_dev_resp_type_t) sdmmc_resp_r1;
131 cmd->cmd_argument = (uint32_t) card->relative_addr << 16;
132 status = sd_send_cmd(card, cmd);
133 if (status != status_success) {
134 return status;
135 }
136
137 card->r1_status.status = cmd->response[0];
138
139 return status;
140 }
141
sd_switch_voltage(sd_card_t * card)142 static hpm_stat_t sd_switch_voltage(sd_card_t *card)
143 {
144 hpm_stat_t status;
145
146 sdmmchost_cmd_t *cmd = &card->host->cmd;
147 memset(cmd, 0, sizeof(*cmd));
148 cmd->cmd_index = sd_voltage_switch;
149 cmd->resp_type = (sdxc_dev_resp_type_t) sdmmc_resp_r1;
150 cmd->cmd_argument = 0;
151 status = sd_send_cmd(card, cmd);
152
153 return status;
154 }
155
sd_send_if_cond(sd_card_t * card)156 static hpm_stat_t sd_send_if_cond(sd_card_t *card)
157 {
158 sdmmchost_cmd_t *cmd = &card->host->cmd;
159 (void) memset(cmd, 0, sizeof(sdmmchost_cmd_t));
160
161 cmd->cmd_index = sd_cmd_send_if_cond;
162 cmd->cmd_argument = 0x1aa;
163 cmd->resp_type = (sdxc_dev_resp_type_t) sdmmc_resp_r7;
164
165 hpm_stat_t status = sd_send_cmd(card, cmd);
166 if (status != status_success) {
167 return status;
168 }
169
170 if ((cmd->response[0] & 0xFFU) != 0xAAU) {
171 return status_sdmmc_card_not_support;
172 }
173
174 return status_success;
175 }
176
sd_decode_csd(sd_card_t * card,uint32_t * raw_csd)177 static void sd_decode_csd(sd_card_t *card, uint32_t *raw_csd)
178 {
179 sd_csd_t *csd = &card->csd;
180
181 csd->csd_structure = (uint8_t) extract_csd_field(raw_csd, 127, 126);
182 csd->data_read_access_time1 = (uint8_t) extract_csd_field(raw_csd, 119, 112);
183 csd->data_read_access_time2 = (uint8_t) extract_csd_field(raw_csd, 111, 104);
184 csd->transfer_speed = (uint8_t) extract_csd_field(raw_csd, 103, 96);
185 csd->card_command_class = (uint16_t) extract_csd_field(raw_csd, 95, 84);
186 csd->read_block_len = (uint8_t) extract_csd_field(raw_csd, 83, 80);
187
188 if (extract_csd_field(raw_csd, 79, 79) != 0U) {
189 csd->support_read_block_partial = true;
190 }
191 if (extract_csd_field(raw_csd, 78, 78) != 0U) {
192 csd->support_write_block_misalignment = true;
193 }
194 if (extract_csd_field(raw_csd, 77, 77) != 0U) {
195 csd->support_read_block_misalignment = true;
196 }
197 if (extract_csd_field(raw_csd, 76, 76) != 0U) {
198 csd->is_dsr_implemented = true;
199 }
200 if (csd->csd_structure == 0U) {
201 csd->device_size = (uint32_t) extract_csd_field(raw_csd, 73, 62);
202 csd->read_current_vdd_min = (uint8_t) extract_csd_field(raw_csd, 61, 59);
203 csd->read_current_vdd_max = (uint8_t) extract_csd_field(raw_csd, 58, 56);
204 csd->write_current_vdd_min = (uint8_t) extract_csd_field(raw_csd, 55, 53);
205 csd->write_current_vdd_max = (uint8_t) extract_csd_field(raw_csd, 52, 50);
206 csd->device_size_multiplier = (uint8_t) extract_csd_field(raw_csd, 49, 47);
207
208 /* Get card total block count and block size. */
209 uint32_t c_size_mult = 1UL << (csd->device_size_multiplier + 2);
210 card->block_count = (csd->device_size + 1U) * c_size_mult;
211 card->block_size = (1UL << (csd->read_block_len));
212 if (card->block_size != SDMMC_BLOCK_SIZE_DEFAULT) {
213 card->block_count *= card->block_size;
214 card->block_size = SDMMC_BLOCK_SIZE_DEFAULT;
215 card->block_count /= card->block_size;
216 }
217 card->card_size_in_bytes = (uint64_t) card->block_size * card->block_count;
218 } else if (csd->csd_structure == 1U) {
219 card->block_size = SDMMC_BLOCK_SIZE_DEFAULT;
220
221 csd->device_size = extract_csd_field(raw_csd, 69, 48);
222 if (csd->device_size >= 0xFFFFU) {
223 csd->support_sdxc = true;
224 }
225 card->block_count = ((csd->device_size + 1U) * 1024U);
226 card->card_size_in_bytes = (uint64_t) (csd->device_size + 1U) * 512UL * 1024UL;
227 } else {
228 /* Unsupported csd version */
229 }
230
231 if (extract_csd_field(raw_csd, 46, 46) != 0U) {
232 csd->is_erase_block_enabled = true;
233 }
234 csd->erase_sector_size = (1UL + extract_csd_field(raw_csd, 45, 39)) * card->block_size;
235 csd->write_protect_group_size = (1UL + extract_csd_field(raw_csd, 38, 32)) * card->block_size;
236 if (extract_csd_field(raw_csd, 31, 31) != 0U) {
237 csd->is_write_protection_group_enabled = true;
238 }
239 csd->write_speed_factor = (uint8_t) extract_csd_field(raw_csd, 28, 26);
240 csd->max_write_block_len = 1UL << extract_csd_field(raw_csd, 25, 22);
241 if (extract_csd_field(raw_csd, 21, 21) != 0U) {
242 csd->support_write_block_partial = true;
243 }
244 if (extract_csd_field(raw_csd, 15, 15) != 0U) {
245 csd->support_file_format_group = true;
246 }
247 if (extract_csd_field(raw_csd, 14, 14) != 0U) {
248 csd->support_copy = true;
249 }
250 if (extract_csd_field(raw_csd, 13, 13) != 0U) {
251 csd->support_permanent_write_protect = true;
252 }
253 if (extract_csd_field(raw_csd, 12, 12) != 0U) {
254 csd->support_temporary_write_protect = true;
255 }
256 csd->file_format = (uint8_t) extract_csd_field(raw_csd, 11, 10);
257
258
259 uint32_t tran_speed = extract_csd_field(raw_csd, 103, 96);
260 uint32_t bitrate_unit = tran_speed & 0x7U;
261 uint32_t time_value = (tran_speed >> 3) & 0xFU;
262 const uint32_t bitrate_unit_list[8] = {100UL * SPEED_1Kbps, SPEED_1Mbps, 10U * SPEED_1Mbps, 100U * SPEED_1Mbps, 0,
263 0, 0, 0};
264 const uint32_t time_value_list[16] = {0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80};
265 card->max_freq = bitrate_unit_list[bitrate_unit] / 10U * time_value_list[time_value];
266 }
267
sd_send_csd(sd_card_t * card)268 static hpm_stat_t sd_send_csd(sd_card_t *card)
269 {
270 sdmmchost_cmd_t *cmd = &card->host->cmd;
271 (void) memset(cmd, 0, sizeof(sdmmchost_cmd_t));
272
273 cmd->cmd_index = sd_cmd_send_csd;
274 cmd->cmd_argument = (uint32_t) card->relative_addr << 16;
275 cmd->resp_type = (sdxc_dev_resp_type_t) sdmmc_resp_r2;
276
277 hpm_stat_t status = sd_send_cmd(card, cmd);
278 if (status != status_success) {
279 return status;
280 }
281
282 uint32_t temp_buf[4];
283 memcpy(temp_buf, cmd->response, sizeof(temp_buf));
284 sd_decode_csd(card, temp_buf);
285
286 return status_success;
287 }
288
289
sd_all_send_cid(sd_card_t * card)290 static hpm_stat_t sd_all_send_cid(sd_card_t *card)
291 {
292 sdmmchost_cmd_t *cmd = &card->host->cmd;
293 (void) memset(cmd, 0, sizeof(sdmmchost_cmd_t));
294
295 cmd->cmd_index = sd_cmd_all_send_cid;
296 cmd->resp_type = (sdxc_dev_resp_type_t) sdmmc_resp_r2;
297
298 hpm_stat_t status = sd_send_cmd(card, cmd);
299 if (status != status_success) {
300 return status;
301 }
302
303 for (uint32_t i = 0; i < 4; i++) {
304 card->cid.cid_words[i] = cmd->response[i];
305 }
306
307 return status;
308 }
309
sd_send_rca(sd_card_t * card)310 static hpm_stat_t sd_send_rca(sd_card_t *card)
311 {
312 sdmmchost_cmd_t *cmd = &card->host->cmd;
313 (void) memset(cmd, 0, sizeof(sdmmchost_cmd_t));
314
315 cmd->cmd_index = sd_cmd_send_relative_addr;
316 cmd->resp_type = (sdxc_dev_resp_type_t) sdmmc_resp_r6;
317
318 hpm_stat_t status = sd_send_cmd(card, cmd);
319 if (status != status_success) {
320 return status;
321 }
322 card->relative_addr = cmd->response[0] >> 16;
323
324 return status;
325 }
326
sd_error_recovery(sd_card_t * card)327 static hpm_stat_t sd_error_recovery(sd_card_t *card)
328 {
329 sdmmchost_cmd_t *cmd = &card->host->cmd;
330 cmd->cmd_index = sdmmc_cmd_stop_transmission;
331 cmd->cmd_type = sdxc_cmd_type_abort_cmd;
332 cmd->resp_type = (sdxc_dev_resp_type_t) sdmmc_resp_r1b;
333
334 return sdmmchost_error_recovery(card->host, cmd);
335 }
336
sd_app_cmd_send_cond_op(sd_card_t * card,sd_ocr_t ocr)337 static hpm_stat_t sd_app_cmd_send_cond_op(sd_card_t *card, sd_ocr_t ocr)
338 {
339 hpm_stat_t status = sdmmc_send_application_command(card->host, card->relative_addr);
340 sdmmchost_cmd_t *cmd = &card->host->cmd;
341 if (status == status_success) {
342 (void) memset(cmd, 0, sizeof(sdmmchost_cmd_t));
343
344 cmd->cmd_index = sd_acmd_sd_send_op_cond;
345 cmd->cmd_argument = ocr.ocr_word;
346 cmd->resp_type = (sdxc_dev_resp_type_t) sdmmc_resp_r3;
347 status = sd_send_cmd(card, cmd);
348 }
349 return status;
350 }
351
sd_app_cmd_set_write_block_erase_count(sd_card_t * card,uint32_t block_count)352 static hpm_stat_t sd_app_cmd_set_write_block_erase_count(sd_card_t *card, uint32_t block_count)
353 {
354 hpm_stat_t status = sdmmc_send_application_command(card->host, card->relative_addr);
355 sdmmchost_cmd_t *cmd = &card->host->cmd;
356 if (status == status_success) {
357 (void) memset(cmd, 0, sizeof(sdmmchost_cmd_t));
358
359 cmd->cmd_index = sd_acmd_set_wr_blk_erase_count;
360 cmd->cmd_argument = block_count;
361 cmd->resp_type = (sdxc_dev_resp_type_t) sdmmc_resp_r1;
362 status = sd_send_cmd(card, cmd);
363 }
364
365 return status;
366 }
367
sd_probe_bus_voltage(sd_card_t * card)368 static hpm_stat_t sd_probe_bus_voltage(sd_card_t *card)
369 {
370 hpm_stat_t status = status_invalid_argument;
371
372 do {
373 status = sdmmc_go_idle_state(card->host, 0);
374 HPM_BREAK_IF(status != status_success);
375
376 status = sd_send_if_cond(card);
377 if (status == status_sdmmc_card_not_support) {
378 status = sdmmc_go_idle_state(card->host, 0);
379 HPM_BREAK_IF(status != status_success);
380 }
381 sd_ocr_t ocr = {.ocr_word = 0};
382 const sd_ocr_t sdxc_ocr = {.ocr_word = 0x40ff8000UL};
383
384 /* Query OCR */
385 status = sd_app_cmd_send_cond_op(card, ocr);
386 HPM_BREAK_IF(status != status_success);
387 sdmmchost_cmd_t *cmd = &card->host->cmd;
388 ocr.ocr_word = cmd->response[0];
389 ocr.ocr_word &= sdxc_ocr.ocr_word;
390 ocr.card_capacity_status = 1;
391 if (sdmmchost_is_voltage_switch_supported(card->host)) {
392 ocr.switching_to_1v8_accepted = 1;
393 }
394
395 /* Switch Operation condition */
396 sd_ocr_t recv_ocr = {.ocr_word = 0};
397 do {
398 status = sd_app_cmd_send_cond_op(card, ocr);
399 HPM_BREAK_IF(status != status_success);
400 recv_ocr.ocr_word = cmd->response[0];
401 } while (recv_ocr.card_power_up_status == 0);
402
403 if (recv_ocr.card_capacity_status == 0) {
404 card->sd_flags.is_byte_addressing_mode = 1;
405 }
406
407 card->ocr.ocr_word = recv_ocr.ocr_word;
408
409 if (sdmmchost_is_voltage_switch_supported(card->host) && (card->ocr.switching_to_1v8_accepted != 0U)) {
410 status = sd_switch_voltage(card);
411 HPM_BREAK_IF(status != status_success);
412
413 status = sdmmchost_switch_to_1v8(card->host);
414 HPM_BREAK_IF(status != status_success);
415
416 card->operation_voltage = sdmmc_operation_voltage_1v8;
417 } else {
418 card->operation_voltage = sdmmc_operation_voltage_3v3;
419 }
420
421 } while (false);
422
423 return status;
424 }
425
sd_be2le(uint32_t be)426 uint32_t sd_be2le(uint32_t be)
427 {
428 uint32_t value = be;
429
430 uint8_t *be_u8 = (uint8_t *) &value;
431
432 for (uint32_t i = 0; i < 2; i++) {
433 uint8_t tmp = be_u8[i];
434 be_u8[i] = be_u8[3 - i];
435 be_u8[3 - i] = tmp;
436 }
437
438 return value;
439 }
440
sd_send_scr(sd_card_t * card)441 static hpm_stat_t sd_send_scr(sd_card_t *card)
442 {
443 hpm_stat_t status = status_invalid_argument;
444
445 status = sdmmc_send_application_command(card->host, card->relative_addr);
446 if (status != status_success) {
447 return status;
448 }
449
450 sdmmchost_cmd_t *cmd = &card->host->cmd;
451 (void) memset(cmd, 0, sizeof(*cmd));
452 cmd->cmd_index = sd_acmd_send_scr;
453 cmd->resp_type = (sdxc_dev_resp_type_t) sdmmc_resp_r1;
454 sdmmchost_data_t *data = &card->host->data;
455 memset(data, 0, sizeof(*data));
456 data->block_size = 8;
457 data->block_cnt = 1;
458 data->rx_data = card->host->buffer;
459 sdmmchost_xfer_t *content = &card->host->xfer;
460 content->data = data;
461 content->command = cmd;
462 status = sd_transfer(card, content);
463 if (status != status_success) {
464 return status;
465 }
466
467 /* Get SCR value */
468 sd_scr_t scr;
469 scr.scr_word[0] = data->rx_data[0];
470 scr.scr_word[1] = data->rx_data[1];
471 sd_convert_data_endian(&scr.scr_word[0], ARRAY_SIZE(scr.scr_word));
472
473 sd_decode_scr(card, &scr.scr_word[0]);
474
475 return status;
476 }
477
sd_decode_scr(sd_card_t * card,uint32_t * raw_scr)478 void sd_decode_scr(sd_card_t *card, uint32_t *raw_scr)
479 {
480 sd_scr_t *scr = &card->scr;
481
482 scr->scr_word[0] = raw_scr[0];
483 scr->scr_word[1] = raw_scr[1];
484
485 if ((scr->sd_bus_widths & 0x04) != 0) {
486 card->sd_flags.support_4bit_width = 1;
487 }
488 if (scr->support_cmd20 == 1) {
489 card->sd_flags.support_speed_class_control_cmd = 1;
490 }
491 if (scr->support_cmd23) {
492 card->sd_flags.support_set_block_count_cmd = 1;
493 }
494 }
495
sd_check_card_parameters(sd_card_t * card)496 static hpm_stat_t sd_check_card_parameters(sd_card_t *card)
497 {
498 hpm_stat_t status;
499 if ((card == NULL) || (card->host == NULL) || (card->host->host_param.base == NULL)) {
500 status = status_invalid_argument;
501 } else if (!sdmmchost_is_card_detected(card->host)) {
502 status = status_sdmmc_device_init_required;
503 } else {
504 card->host->card_inserted = true;
505 status = status_success;
506 }
507 return status;
508 }
509
510
sd_set_bus_width(sd_card_t * card,sdmmc_buswidth_t buswidth)511 static hpm_stat_t sd_set_bus_width(sd_card_t *card, sdmmc_buswidth_t buswidth)
512 {
513 hpm_stat_t status = sdmmc_send_application_command(card->host, card->relative_addr);
514 if (status != status_success) {
515 return status;
516 }
517
518 sdmmchost_cmd_t *cmd = &card->host->cmd;
519 memset(cmd, 0, sizeof(*cmd));
520 cmd->cmd_index = sd_acmd_set_bus_width;
521 cmd->resp_type = (sdxc_dev_resp_type_t) sdmmc_resp_r1;
522
523 if (buswidth == sdmmc_bus_width_1bit) {
524 cmd->cmd_argument = 0;
525 } else if (buswidth == sdmmc_bus_width_4bit) {
526 cmd->cmd_argument = 2;
527 } else {
528 return status_invalid_argument;
529 }
530 status = sd_send_cmd(card, cmd);
531
532 return status;
533 }
534
sd_set_bus_timing(sd_card_t * card,sdmmc_speed_mode_t timing_mode)535 static hpm_stat_t sd_set_bus_timing(sd_card_t *card, sdmmc_speed_mode_t timing_mode)
536 {
537 hpm_stat_t status;
538 uint32_t timing_mode_option = (uint32_t) sd_timing_sdr25_highspeed;
539 uint32_t clock_option = SD_CLOCK_50MHZ;
540 bool need_reverse = true;
541 sdmmc_speed_mode_t speed;
542 switch (timing_mode) {
543 default:
544 clock_option = SD_CLOCK_25MHZ;
545 speed = sdmmc_sd_speed_sdr12;
546 timing_mode_option = sd_timing_sdr12_default;
547 break;
548 case sd_timing_sdr25_highspeed:
549 clock_option = SD_CLOCK_50MHZ;
550 speed = sdmmc_sd_speed_sdr25;
551 timing_mode_option = sd_timing_sdr25_highspeed;
552 break;
553 case sd_timing_sdr50:
554 clock_option = SD_CLOCK_100MHZ;
555 speed = sdmmc_sd_speed_sdr50;
556 timing_mode_option = sd_timing_sdr50;
557 break;
558 case sd_timing_ddr50:
559 need_reverse = false;
560 clock_option = SD_CLOCK_50MHZ;
561 speed = sdmmc_sd_speed_ddr50;
562 timing_mode_option = sd_timing_ddr50;
563 break;
564 case sd_timing_sdr104:
565 clock_option = SD_CLOCK_208MHZ;
566 speed = sdmmc_sd_speed_sdr104;
567 timing_mode_option = sd_timing_sdr104;
568 break;
569 }
570
571 card->current_timing = speed;
572
573 status = sd_switch_function(card, (uint32_t) sd_switch_function_mode_set,
574 (uint32_t) sd_switch_function_group_access_mode, timing_mode_option);
575 if (status != status_success) {
576 return status;
577 }
578
579 sdmmchost_set_speed_mode(card->host, speed);
580 card->host->clock_freq = sdmmchost_set_card_clock(card->host, clock_option, need_reverse);
581 return status;
582 }
583
sd_decode_status(sd_card_t * card,uint32_t * raw_status)584 static void sd_decode_status(sd_card_t *card, uint32_t *raw_status)
585 {
586 sd_raw_status_t *sd_raw_status = (sd_raw_status_t *) raw_status;
587
588 card->status.bus_width = sd_raw_status->data_bus_width;
589 card->status.secure_mode = sd_raw_status->secured_mode;
590 card->status.card_type = sd_raw_status->sd_card_type;
591 card->status.protected_size = sd_raw_status->size_of_protected_area;
592 switch (sd_raw_status->speed_class) {
593 case 0:
594 card->status.speed_class = 0;
595 break;
596 case 1:
597 card->status.speed_class = 2;
598 break;
599 case 2:
600 card->status.speed_class = 4;
601 break;
602 case 3:
603 card->status.speed_class = 6;
604 break;
605 case 4:
606 card->status.speed_class = 10;
607 break;
608 default:
609 card->status.speed_class = 0;
610 break;
611 }
612 card->status.performance_move = sd_raw_status->performance_move;
613 if (sd_raw_status->au_size < 0xB) {
614 card->status.au_size = (0x4000UL << sd_raw_status->au_size);
615 } else {
616 switch (sd_raw_status->au_size) {
617 case 0xB:
618 card->status.au_size = SIZE_1MB * 12;
619 break;
620 case 0xC:
621 card->status.au_size = SIZE_1MB * 16;
622 break;
623 case 0xD:
624 card->status.au_size = SIZE_1MB * 24;
625 break;
626 case 0xE:
627 card->status.au_size = SIZE_1MB * 32;
628 break;
629 default:
630 card->status.au_size = SIZE_1MB * 64;
631 break;
632 }
633 }
634
635 card->status.erase_size = sd_raw_status->au_size * sd_raw_status->erase_size;
636 card->status.uhs_au_size = (0x4000UL << sd_raw_status->uhs_au_size);
637 card->status.erase_timeout = sd_raw_status->erase_timeout;
638 card->status.uhs_speed_grade = sd_raw_status->uhs_speed_grade;
639 }
640
sd_card_deinit(sd_card_t * card)641 void sd_card_deinit(sd_card_t *card)
642 {
643 (void) card;
644 }
645
sd_host_init(sd_card_t * card)646 hpm_stat_t sd_host_init(sd_card_t *card)
647 {
648 hpm_stat_t status = status_success;
649 assert(card != NULL);
650
651 status = sdmmchost_init(card->host);
652 if (status == status_success) {
653 card->is_host_ready = true;
654 card->operation_voltage = sdmmc_operation_voltage_3v3;
655 }
656
657 return status_success;
658 }
659
660
sd_init(sd_card_t * card)661 hpm_stat_t sd_init(sd_card_t *card)
662 {
663 hpm_stat_t status = status_invalid_argument;
664 do {
665 HPM_BREAK_IF(card == NULL);
666
667 status = sd_host_init(card);
668 HPM_BREAK_IF(status != status_success);
669
670 card->host->card_init_done = false;
671 card->relative_addr = 0;
672 card->current_timing = sdmmc_sd_speed_normal;
673
674 /* Check whether card is present */
675 int32_t delay_cnt = 10;
676 while (!sd_is_card_present(card)) {
677 card->host->host_param.delay_ms(100);
678 delay_cnt--;
679 if (delay_cnt < 0) {
680 break;
681 }
682 }
683 if (!sd_is_card_present(card)) {
684 status = status_sdmmc_wait_card_insert_timeout;
685 break;
686 }
687 card->host->card_inserted = true;
688 sdmmchost_delay_ms(card->host, 100); /* Wait a while in case the card connection is still not stable */
689
690 status = sd_card_init(card);
691
692 } while (false);
693
694 return status;
695 }
696
sd_deinit(sd_card_t * card)697 void sd_deinit(sd_card_t *card)
698 {
699 (void) card;
700 }
701
702
sd_card_init(sd_card_t * card)703 hpm_stat_t sd_card_init(sd_card_t *card)
704 {
705 hpm_stat_t status = sd_check_card_parameters(card);
706 do {
707 HPM_BREAK_IF(status != status_success);
708
709 sdmmchost_set_card_bus_width(card->host, sdmmc_bus_width_1bit);
710 sdmmchost_set_card_clock(card->host, SDMMC_CLOCK_400KHZ, true);
711 status = sd_probe_bus_voltage(card);
712 card->host->operation_mode = hpm_sdmmc_operation_mode_identification;
713 sdmmchost_init_io(card->host, card->host->operation_mode);
714
715 HPM_BREAK_IF(status != status_success);
716
717 card->host->dev_type = sdmmc_dev_type_sd;
718
719 /* Send CMD2 */
720 status = sd_all_send_cid(card);
721 HPM_BREAK_IF(status != status_success);
722 /* Send CMD3 */
723 status = sd_send_rca(card);
724 HPM_BREAK_IF(status != status_success);
725 /* Send CMD9 */
726 status = sd_send_csd(card);
727 HPM_BREAK_IF(status != status_success);
728 /* Send CMD7 */
729 status = sd_select_card(card, true);
730 HPM_BREAK_IF(status != status_success);
731
732 sdmmchost_set_card_clock(card->host, SD_CLOCK_25MHZ, true);
733 card->host->operation_mode = hpm_sdmmc_operation_mode_transfer;
734 sdmmchost_init_io(card->host, card->host->operation_mode);
735
736 /* Send ACMD13 */
737 status = sd_read_status(card);
738 HPM_BREAK_IF(status != status_success);
739
740 /* Send ACMD51 */
741 status = sd_send_scr(card);
742 HPM_BREAK_IF(status != status_success);
743
744 /* TODO: Add CMD42 handling if the CARD in under locked state */
745
746 /* Send ACMD6 */
747 bool support_4bit = IS_HPM_BITMASK_SET(card->host->host_param.host_flags, HPM_SDMMC_HOST_SUPPORT_4BIT);
748 if (support_4bit && (card->sd_flags.support_4bit_width != 0)) {
749 status = sd_set_bus_width(card, sdmmc_bus_width_4bit);
750 if (status != status_success) {
751 return status;
752 }
753 sdmmchost_set_card_bus_width(card->host, sdmmc_bus_width_4bit);
754 }
755 /* Send CMD16: Set block size */
756 status = sdmmc_set_block_size(card->host, SDMMC_BLOCK_SIZE_DEFAULT);
757 if (status != status_success) {
758 return status;
759 }
760
761 /***************************************************************************************************************
762 *
763 * Switch to specified highest frequency
764 *
765 * Steps:
766 *
767 * 1. Find the allowed maximum speed mode
768 * 2. Switch to the maximum speed mode following the eMMC specification
769 *
770 **************************************************************************************************************/
771
772 sdmmc_speed_mode_t speed_mode = sdmmc_sd_speed_normal;
773 bool support_1v8 = IS_HPM_BITMASK_SET(card->host->host_param.host_flags, HPM_SDMMC_HOST_SUPPORT_1V8);
774 bool support_ddr = IS_HPM_BITMASK_SET(card->host->host_param.host_flags, HPM_SDMMC_HOST_SUPPORT_DDR);
775 bool support_sdr104 = IS_HPM_BITMASK_SET(card->host->host_param.host_flags, HPM_SDMMC_HOST_SUPPORT_SDR104);
776 bool support_sdr50 = IS_HPM_BITMASK_SET(card->host->host_param.host_flags, HPM_SDMMC_HOST_SUPPORT_SDR50);
777
778 bool need_manual_set_cardclk_delay_chain = false;
779 if (card->operation_voltage == sdmmc_operation_voltage_1v8) {
780 if (support_sdr104 && support_1v8 && support_4bit) {
781 speed_mode = sdmmc_sd_speed_sdr104;
782 } else if (support_sdr50 && support_1v8 && support_4bit) {
783 speed_mode = sdmmc_sd_speed_sdr50;
784 } else if (support_ddr && support_1v8 && support_4bit) {
785 speed_mode = sdmmc_sd_speed_ddr50;
786 need_manual_set_cardclk_delay_chain = true;
787 } else {
788 speed_mode = sdmmc_sd_speed_high;
789 }
790 } else {
791 speed_mode = sdmmc_sd_speed_high;
792 }
793
794 /* Send CMD6: Set bus timing */
795 status = sd_set_bus_timing(card, speed_mode);
796 HPM_BREAK_IF(status != status_success);
797
798 /* Perform Tuning process if necessary */
799 if ((card->current_timing == sdmmc_sd_speed_sdr50) || (card->current_timing == sdmmc_sd_speed_sdr104)) {
800 status = sdmmc_enable_auto_tuning(card->host);
801 HPM_BREAK_IF(status != status_success);
802 }
803
804 /** Send CMD: Set power limit */
805 status = sd_set_max_current(card, sd_current_limit_600ma);
806 HPM_BREAK_IF(status != status_success);
807
808 /* Switch to 1.8V signaling, mandatory for DDR50 mode */
809 if (speed_mode == sdmmc_sd_speed_ddr50) {
810 sdmmchost_select_voltage(card->host, hpm_sdmmc_io_voltage_1v8);
811 }
812
813 if (need_manual_set_cardclk_delay_chain) {
814 (void) sdmmchost_set_cardclk_delay_chain(card->host);
815 }
816
817 /* Try to get new CSD and look up the TRAN_SPEED */
818 status = sd_select_card(card, false);
819 HPM_BREAK_IF(status != status_success);
820 status = sd_send_csd(card);
821 HPM_BREAK_IF(status != status_success);
822
823 status = sd_select_card(card, true);
824 HPM_BREAK_IF(status != status_success);
825
826 } while (false);
827
828 if (status == status_success) {
829 card->host->card_init_done = true;
830 }
831
832 return status;
833 }
834
835
sd_is_card_present(sd_card_t * card)836 bool sd_is_card_present(sd_card_t *card)
837 {
838 return sdmmchost_is_card_detected(card->host);
839 }
840
sd_select_card(sd_card_t * card,bool is_selected)841 hpm_stat_t sd_select_card(sd_card_t *card, bool is_selected)
842 {
843 uint16_t rca = (is_selected) ? card->relative_addr : 0;
844 return sdmmc_select_card(card->host, rca, is_selected);
845 }
846
sd_read_status(sd_card_t * card)847 hpm_stat_t sd_read_status(sd_card_t *card)
848 {
849 hpm_stat_t status = sdmmc_send_application_command(card->host, card->relative_addr);
850 if (status != status_success) {
851 return status;
852 }
853
854 sdmmchost_cmd_t *cmd = &card->host->cmd;
855 sdmmchost_data_t *data = &card->host->data;
856 sdmmchost_xfer_t *content = &card->host->xfer;
857 cmd->cmd_index = sd_acmd_sd_status;
858 cmd->resp_type = (sdxc_dev_resp_type_t) sdmmc_resp_r1;
859 data->block_size = 64;
860 data->block_cnt = 1;
861 data->rx_data = card->host->buffer;
862 content->data = data;
863 content->command = cmd;
864 status = sd_transfer(card, content);
865 if (status != status_success) {
866 return status;
867 }
868 uint32_t raw_status[16];
869 memcpy(raw_status, card->host->buffer, 64);
870 sd_convert_data_endian(raw_status, ARRAY_SIZE(raw_status));
871
872 sd_decode_status(card, raw_status);
873
874 return status;
875 }
876
sd_read_blocks(sd_card_t * card,uint8_t * buffer,uint32_t start_block,uint32_t block_count)877 hpm_stat_t sd_read_blocks(sd_card_t *card, uint8_t *buffer, uint32_t start_block, uint32_t block_count)
878 {
879 hpm_stat_t status = sd_check_card_parameters(card);
880 do {
881 HPM_BREAK_IF(status != status_success);
882
883 if (!card->host->card_init_done) {
884 status = status_sdmmc_device_init_required;
885 break;
886 }
887
888 sdmmchost_cmd_t *cmd = &card->host->cmd;
889 sdmmchost_data_t *data = &card->host->data;
890 sdmmchost_xfer_t *content = &card->host->xfer;
891 memset(cmd, 0, sizeof(*cmd));
892 memset(data, 0, sizeof(*data));
893 memset(content, 0, sizeof(*content));
894
895 while (block_count > 0) {
896 uint32_t read_block_count = (block_count >= MAX_BLOCK_COUNT) ? MAX_BLOCK_COUNT : block_count;
897 if (read_block_count > 1) {
898 cmd->cmd_index = sdmmc_cmd_read_multiple_block;
899 if (card->sd_flags.support_set_block_count_cmd != 0) {
900 data->enable_auto_cmd23 = true;
901 } else {
902 data->enable_auto_cmd12 = true;
903 }
904 } else {
905 cmd->cmd_index = sdmmc_cmd_read_single_block;
906 }
907
908 uint32_t start_addr = start_block;
909 if (card->sd_flags.is_byte_addressing_mode == 1U) {
910 start_addr *= card->block_size;
911 }
912 cmd->resp_type = (sdxc_dev_resp_type_t) sdmmc_resp_r1;
913 cmd->cmd_argument = start_addr;
914 data->block_size = SDMMC_BLOCK_SIZE_DEFAULT;
915 data->block_cnt = read_block_count;
916 data->rx_data = (uint32_t *) sdmmc_get_sys_addr(card->host, (uint32_t) buffer);
917 content->data = data;
918 content->command = cmd;
919 uint32_t aligned_start = HPM_L1C_CACHELINE_ALIGN_DOWN((uint32_t) data->rx_data);
920 uint32_t end_addr = (uint32_t) data->rx_data + card->block_size * block_count;
921 uint32_t aligned_end = HPM_L1C_CACHELINE_ALIGN_UP(end_addr);
922 uint32_t aligned_size = aligned_end - aligned_start;
923 l1c_dc_flush(aligned_start, aligned_size);
924 status = sd_transfer(card, content);
925 l1c_dc_invalidate(aligned_start, aligned_size);
926 if (status != status_success) {
927 break;
928 }
929 block_count -= read_block_count;
930 start_block += read_block_count;
931 buffer += SDMMC_BLOCK_SIZE_DEFAULT * read_block_count;
932 }
933 } while (false);
934
935 return status;
936 }
937
sd_write_blocks(sd_card_t * card,const uint8_t * buffer,uint32_t start_block,uint32_t block_count)938 hpm_stat_t sd_write_blocks(sd_card_t *card, const uint8_t *buffer, uint32_t start_block, uint32_t block_count)
939 {
940 hpm_stat_t status = sd_check_card_parameters(card);
941 do {
942 HPM_BREAK_IF(status != status_success);
943
944 if (!card->host->card_init_done) {
945 status = status_sdmmc_device_init_required;
946 break;
947 }
948
949 sdmmchost_cmd_t *cmd = &card->host->cmd;
950 sdmmchost_data_t *data = &card->host->data;
951 sdmmchost_xfer_t *content = &card->host->xfer;
952 memset(cmd, 0, sizeof(*cmd));
953 memset(data, 0, sizeof(*data));
954 memset(content, 0, sizeof(*content));
955
956 status = sd_polling_card_status_busy(card, WRITE_BLOCK_TIMEOUT_IN_MS);
957 HPM_BREAK_IF(status != status_success);
958 while (block_count > 0) {
959 uint32_t write_block_count = (block_count >= MAX_BLOCK_COUNT) ? MAX_BLOCK_COUNT : block_count;
960
961 /* If the card is not an SDUC card, issue ACMD23 to accelerate write performance */
962 if (card->csd.csd_structure <= 1) {
963 status = sd_app_cmd_set_write_block_erase_count(card, write_block_count);
964 HPM_BREAK_IF(status != status_success);
965 }
966 if (write_block_count > 1) {
967 cmd->cmd_index = sdmmc_cmd_write_multiple_block;
968 if (card->sd_flags.support_set_block_count_cmd != 0) {
969 data->enable_auto_cmd23 = true;
970 } else {
971 data->enable_auto_cmd12 = true;
972 }
973 } else {
974 cmd->cmd_index = sdmmc_cmd_write_single_block;
975 data->enable_auto_cmd12 = false;
976 }
977 uint32_t start_addr = start_block;
978 if (card->sd_flags.is_byte_addressing_mode == 1U) {
979 start_addr *= card->block_size;
980 }
981 cmd->resp_type = (sdxc_dev_resp_type_t) sdmmc_resp_r1;
982 cmd->cmd_argument = start_addr;
983 data->block_size = SDMMC_BLOCK_SIZE_DEFAULT;
984 data->block_cnt = write_block_count;
985 data->tx_data = (const uint32_t *) sdmmc_get_sys_addr(card->host, (uint32_t) buffer);
986 content->data = data;
987 content->command = cmd;
988 uint32_t aligned_start = HPM_L1C_CACHELINE_ALIGN_DOWN((uint32_t) data->tx_data);
989 uint32_t aligned_end = HPM_L1C_CACHELINE_ALIGN_UP(
990 (uint32_t) data->tx_data + card->block_size * write_block_count);
991 uint32_t aligned_size = aligned_end - aligned_start;
992 l1c_dc_flush(aligned_start, aligned_size);
993 status = sd_transfer(card, content);
994 if (status != status_success) {
995 break;
996 }
997 status = sd_polling_card_status_busy(card, WRITE_BLOCK_TIMEOUT_IN_MS);
998 HPM_BREAK_IF(status != status_success);
999 block_count -= write_block_count;
1000 start_block += write_block_count;
1001 buffer += SDMMC_BLOCK_SIZE_DEFAULT * write_block_count;
1002 }
1003
1004 } while (false);
1005
1006 return status;
1007 }
1008
1009 /**
1010 * @brief Calculate SD erase timeout value
1011 * Refer to SD_Specification_Part1_Physical_Layer_Specification_Version4.20.pdf, section 4.14 for more details.
1012 */
sd_calculate_erase_timeout(sd_card_t * card,uint32_t start_block,uint32_t block_count)1013 static uint32_t sd_calculate_erase_timeout(sd_card_t *card, uint32_t start_block, uint32_t block_count)
1014 {
1015 uint32_t erase_timeout;
1016 if (card->status.erase_timeout == 0) {
1017 erase_timeout = block_count * 250U;
1018 } else {
1019 uint32_t blocks_per_au = card->status.au_size / card->block_size;
1020 uint32_t start_block_offset_in_au = start_block % blocks_per_au;
1021 uint32_t end_block = start_block + block_count;
1022 uint32_t end_block_offset_in_au = end_block % blocks_per_au;
1023 uint32_t extra_timeout_in_ms = 0;
1024 extra_timeout_in_ms += (start_block_offset_in_au > 0) ? 250 : 0;
1025 extra_timeout_in_ms += (end_block_offset_in_au > 0) ? 250 : 0;
1026
1027 uint32_t full_erase_au_count = (block_count - (blocks_per_au - start_block_offset_in_au)) / blocks_per_au;
1028
1029 /* Erase timeout = Terase/Nerase * AU_COUNT + ERASE_OFFSET */
1030 erase_timeout = 1000U * card->status.erase_timeout / card->status.erase_size * full_erase_au_count +
1031 card->status.erase_offset * 1000;
1032 if (erase_timeout < 1000) {
1033 erase_timeout = 1000;
1034 }
1035 erase_timeout += extra_timeout_in_ms;
1036 }
1037 return erase_timeout;
1038 }
1039
sd_erase_blocks(sd_card_t * card,uint32_t start_block,uint32_t block_count)1040 hpm_stat_t sd_erase_blocks(sd_card_t *card, uint32_t start_block, uint32_t block_count)
1041 {
1042 hpm_stat_t status = sd_check_card_parameters(card);
1043 do {
1044 HPM_BREAK_IF(status != status_success);
1045
1046 if (!card->host->card_init_done) {
1047 status = status_sdmmc_device_init_required;
1048 break;
1049 }
1050
1051 sdmmchost_cmd_t *cmd = &card->host->cmd;
1052 memset(cmd, 0, sizeof(*cmd));
1053 uint32_t erase_start_addr = start_block;
1054 uint32_t erase_end_addr = start_block + block_count - 1U;
1055 if (card->sd_flags.is_byte_addressing_mode == 1U) {
1056 erase_start_addr *= card->block_size;
1057 erase_end_addr *= card->block_size;
1058 }
1059 uint32_t erase_timeout = sd_calculate_erase_timeout(card, start_block, block_count);
1060 /* Send erase start */
1061 cmd->cmd_index = sd_cmd_erase_start;
1062 cmd->cmd_argument = erase_start_addr;
1063 cmd->resp_type = (sdxc_dev_resp_type_t) sdmmc_resp_r1;
1064 status = sd_send_cmd(card, cmd);
1065 HPM_BREAK_IF(status != status_success);
1066 /* Send Erase end */
1067 cmd->cmd_index = sd_cmd_erase_end;
1068 cmd->cmd_argument = erase_end_addr;
1069 status = sd_send_cmd(card, cmd);
1070 HPM_BREAK_IF(status != status_success);
1071
1072 /* Send erase command */
1073 cmd->cmd_index = sdmmc_cmd_erase;
1074 cmd->cmd_argument = 0xFF;
1075 cmd->resp_type = (sdxc_dev_resp_type_t) sdmmc_resp_r1b;
1076 cmd->cmd_timeout_ms = erase_timeout;
1077 status = sd_send_cmd(card, cmd);
1078 HPM_BREAK_IF(status != status_success);
1079
1080 /* Wait until erase completed. */
1081 status = sd_polling_card_status_busy(card, erase_timeout);
1082
1083 } while (false);
1084
1085 return status;
1086 }
1087
sd_set_driver_strength(sd_card_t * card,sd_drive_strength_t driver_strength)1088 hpm_stat_t sd_set_driver_strength(sd_card_t *card, sd_drive_strength_t driver_strength)
1089 {
1090 return sd_switch_function(card, (uint32_t) sd_switch_function_mode_set,
1091 (uint32_t) sd_switch_function_group_drive_strength, (uint32_t) driver_strength);
1092 }
1093
sd_set_max_current(sd_card_t * card,sd_max_current_t max_current)1094 hpm_stat_t sd_set_max_current(sd_card_t *card, sd_max_current_t max_current)
1095 {
1096 return sd_switch_function(card, (uint32_t) sd_switch_function_mode_set,
1097 (uint32_t) sd_switch_function_group_power_limit, (uint32_t) max_current);
1098 }
1099
sd_polling_card_status_busy(sd_card_t * card,uint32_t timeout_ms)1100 hpm_stat_t sd_polling_card_status_busy(sd_card_t *card, uint32_t timeout_ms)
1101 {
1102 hpm_stat_t status = status_invalid_argument;
1103 bool is_busy = true;
1104 do {
1105 HPM_BREAK_IF((card == NULL) || (card->host == NULL));
1106
1107 status = sd_send_card_status(card);
1108 if (status != status_success) {
1109 break;
1110 }
1111 if ((card->r1_status.status == sdmmc_state_program) || (card->r1_status.ready_for_data == 0U)) {
1112 is_busy = true;
1113 card->host->host_param.delay_ms(1);
1114 timeout_ms--;
1115 } else {
1116 is_busy = false;
1117 }
1118
1119 } while (is_busy && (timeout_ms > 0));
1120
1121 if ((status == status_success) && is_busy) {
1122 status = status_sdmmc_wait_busy_timeout;
1123 }
1124
1125 return status;
1126 }
1127
sd_switch_function(sd_card_t * card,uint32_t mode,uint32_t group,uint32_t number)1128 hpm_stat_t sd_switch_function(sd_card_t *card, uint32_t mode, uint32_t group, uint32_t number)
1129 {
1130 hpm_stat_t error = status_invalid_argument;
1131
1132 do {
1133 HPM_BREAK_IF((card == NULL) || (group > 6) || (group < 1) || (number > 15U));
1134
1135 sdmmchost_cmd_t *cmd = &card->host->cmd;
1136 sdmmchost_data_t *data = &card->host->data;
1137 sdmmchost_xfer_t *content = &card->host->xfer;
1138 memset(cmd, 0, sizeof(*cmd));
1139 memset(data, 0, sizeof(*data));
1140 memset(content, 0, sizeof(*content));
1141
1142 cmd->cmd_index = sd_cmd_switch;
1143 cmd->resp_type = (sdxc_dev_resp_type_t) sdmmc_resp_r1;
1144 cmd->cmd_argument =
1145 (mode << 31) | (0x00FFFFFFUL & (~(0xFUL << ((group - 1U) * 4)))) | (number << ((group - 1U) * 4));
1146 data->block_size = sizeof(switch_function_status_t);
1147 data->block_cnt = 1;
1148 data->rx_data = (uint32_t *) sdmmc_get_sys_addr(card->host, (uint32_t) &card->host->buffer);
1149 content->data = data;
1150 content->command = cmd;
1151 error = sd_transfer(card, content);
1152 if (error != status_success) {
1153 break;
1154 }
1155
1156 memcpy(card->sfs.status_word, card->host->buffer, sizeof(switch_function_status_t));
1157 sd_convert_data_endian(card->sfs.status_word, ARRAY_SIZE(card->sfs.status_word));
1158
1159 } while (false);
1160
1161 return error;
1162 }
1163