• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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