• 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_emmc.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 #define EMMC_SECTOR_SIZE_DEFAULT (512U)
18 
19 #define SIZE_128KB (128UL * SIZE_1KB)
20 #define SIZE_512KB (512UL * SIZE_1KB)
21 
22 #define EMMC_RCA_DEFAULT (1U)
23 
24 #define EMMC_CSD_VERSION_MAX (2U)
25 #define EMMC_EXT_CSD_REV_MAX (8U)
26 #define EMMC_CMD_SET_REV_MAX (0U)
27 
28 #define EXT_CSD_SECURE_WP_INFO_SECURE_WP_SUPPORT_MASK (1U)
29 #define EXT_CSD_SECURE_WP_INFO_SECURE_WP_EN_STATUS (2U)
30 
31 #define EXT_CSD_BOOT_INFO_ALT_BOOT_MODE_MASK (1U)
32 #define EXT_CSD_BOOT_INFO_DDR_BOOT_MODE_MASK (2U)
33 #define EXT_CSD_BOOT_INFO_HS_BOOT_MODE_MASK (4U)
34 
35 #define EXT_CSD_SEC_FEATURE_SUPPORT_SECURE_ER_EN_MASK (1UL << 0)
36 #define EXT_CSD_SEC_FEATURE_SUPPORT_SEC_BD_BLK_EN_MASK (1UL << 2)
37 #define EXT_CSD_SEC_FEATURE_SUPPORT_SEC_GB_CL_EN_MASK (1UL << 4)
38 #define EXT_CSD_SEC_FEATURE_SUPPORT_SEC_SANITIZE_MASK (1UL << 6)
39 
40 #define EXT_CSD_ERASE_GROUP_DEF_ENABLE_MASK (1UL << 0)
41 
42 
43 #define EXT_CSD_HS_TIMING_COMPATIBLE    (0U)
44 #define EXT_CSD_HS_TIMING_HIGH_SPEED    (1U)
45 #define EXT_CSD_HS_TIMING_HS200         (2U)
46 #define EXT_CSD_HS_TIMING_HS400         (3U)
47 
48 /**
49  * @brief Set Relative Address
50  */
51 static hpm_stat_t emmc_set_rca(emmc_card_t *card, uint16_t relative_addr);
52 
53 /**
54  * @brief Send CSD register
55  */
56 static hpm_stat_t emmc_send_csd(emmc_card_t *card);
57 
58 /**
59  * @brief Send Extend CSD register
60  */
61 static hpm_stat_t emmc_send_ext_csd(emmc_card_t *card);
62 
63 /* Decode Extend CSD */
64 static hpm_stat_t emmc_decode_ext_csd(emmc_card_t *card, emmc_ext_csd_t *ext_csd);
65 
66 /* Polling Card Status register when the card is busy */
67 static hpm_stat_t emmc_polling_card_status_busy(emmc_card_t *card, uint32_t timeout_ms);
68 
69 /* Send OP Condition command */
70 static hpm_stat_t emmc_send_op_cond(emmc_card_t *card, emmc_ocr_t ocr);
71 
72 /* Decode CSD register */
73 static void emmc_decode_csd(emmc_card_t *card, uint32_t *raw_csd);
74 
75 /* Set eMMC Bus Width */
76 static hpm_stat_t emmc_set_bus_width(emmc_card_t *card, emmc_bus_mode_t bus_mode);
77 
78 /* Set eMMC HS Timing */
79 static hpm_stat_t emmc_set_hs_timing(emmc_card_t *card, emmc_hs_timing_t timing);
80 
81 /* Check  */
82 static hpm_stat_t emmc_check_card_parameters(emmc_card_t *card);
83 
84 static hpm_stat_t emmc_error_recovery(emmc_card_t *card);
85 
86 static hpm_stat_t emmc_send_cmd(emmc_card_t *card, sdmmchost_cmd_t *cmd);
87 
88 static hpm_stat_t emmc_transfer(emmc_card_t *card, sdmmchost_xfer_t *content);
89 
emmc_send_cmd(emmc_card_t * card,sdmmchost_cmd_t * cmd)90 static hpm_stat_t emmc_send_cmd(emmc_card_t *card, sdmmchost_cmd_t *cmd)
91 {
92     hpm_stat_t status = sdmmchost_send_command(card->host, cmd);
93 
94     if ((status >= status_sdxc_busy) && (status <= status_sdxc_tuning_failed)) {
95         hpm_stat_t error_recovery_status = emmc_error_recovery(card);
96         if (error_recovery_status != status_success) {
97             status = error_recovery_status;
98         }
99     }
100     return status;
101 }
102 
emmc_transfer(emmc_card_t * card,sdmmchost_xfer_t * content)103 static hpm_stat_t emmc_transfer(emmc_card_t *card, sdmmchost_xfer_t *content)
104 {
105     hpm_stat_t status = sdmmchost_transfer(card->host, content);
106 
107     if ((status >= status_sdxc_busy) && (status <= status_sdxc_tuning_failed)) {
108         hpm_stat_t error_recovery_status = emmc_error_recovery(card);
109         if (error_recovery_status != status_success) {
110             status = error_recovery_status;
111         }
112     }
113     return status;
114 }
115 
emmc_send_card_status(emmc_card_t * card)116 static hpm_stat_t emmc_send_card_status(emmc_card_t *card)
117 {
118     hpm_stat_t status;
119 
120     sdmmchost_cmd_t *cmd = &card->host->cmd;
121     memset(cmd, 0, sizeof(*cmd));
122     cmd->cmd_index = sdmmc_cmd_send_status;
123     cmd->resp_type = (sdxc_dev_resp_type_t) sdmmc_resp_r1;
124     cmd->cmd_argument = (uint32_t) card->relative_addr << 16;
125     status = emmc_send_cmd(card, cmd);
126     if (status != status_success) {
127         return status;
128     }
129 
130     card->current_r1_status.card_status = cmd->response[0];
131 
132     return status;
133 }
134 
emmc_send_op_cond(emmc_card_t * card,emmc_ocr_t ocr)135 static hpm_stat_t emmc_send_op_cond(emmc_card_t *card, emmc_ocr_t ocr)
136 {
137     sdmmchost_cmd_t *cmd = &card->host->cmd;
138     (void) memset(cmd, 0, sizeof(sdmmchost_cmd_t));
139 
140     cmd->cmd_index = emmc_cmd_send_op_cond;
141     cmd->resp_type = (sdxc_dev_resp_type_t) sdmmc_resp_r3;
142     cmd->cmd_argument = ocr.ocr_word;
143 
144     hpm_stat_t status = emmc_send_cmd(card, cmd);
145     if (status != status_success) {
146         return status;
147     }
148 
149     return status_success;
150 }
151 
emmc_decode_csd(emmc_card_t * card,uint32_t * raw_csd)152 static void emmc_decode_csd(emmc_card_t *card, uint32_t *raw_csd)
153 {
154     emmc_csd_t *csd = &card->csd;
155 
156     csd->sector_size = EMMC_SECTOR_SIZE_DEFAULT;
157     csd->csd_structure = extract_csd_field(raw_csd, 127, 126);
158     csd->spec_version = (uint8_t) extract_csd_field(raw_csd, 125, 122);
159     uint8_t taac = (uint8_t) extract_csd_field(raw_csd, 119, 112);
160     uint8_t nsac = (uint8_t) extract_csd_field(raw_csd, 111, 104);
161 
162     uint32_t taac_time_unit_ns[8] = {1UL, 10UL, 100UL, 1000UL, 10000UL, 100000UL, 1000000UL, 10000000UL};
163     uint32_t taac_mult_factor[16] = {0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80};
164     uint8_t taac_time_unit = taac & 0x07;
165     uint8_t taac_mult_fact = (taac >> 3) & 0xFU;
166     csd->taac_ns = taac_time_unit_ns[taac_time_unit] * taac_mult_factor[taac_mult_fact];
167     csd->nsac_cycles = 100UL * nsac;
168 
169     uint32_t tran_speed = (uint8_t) extract_csd_field(raw_csd, 103, 96);
170     uint32_t bitrate_unit = tran_speed & 0x7U;
171     uint32_t time_value = (tran_speed >> 3) & 0xFU;
172     const uint32_t bitrate_unit_list[8] = {100UL * SPEED_1Kbps, SPEED_1Mbps, 10U * SPEED_1Mbps, 100U * SPEED_1Mbps, 0,
173                                            0, 0, 0};
174     const uint32_t time_value_list[16] = {0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80};
175     csd->max_freq = bitrate_unit_list[bitrate_unit] / 10U * time_value_list[time_value];
176 
177     csd->card_command_class = (uint16_t) extract_csd_field(raw_csd, 95, 84);
178 
179     uint32_t read_bl_len = (uint8_t) extract_csd_field(raw_csd, 83, 80);
180     csd->max_read_block_len = 1UL << read_bl_len;
181 
182     csd->support_read_block_partial = (extract_csd_field(raw_csd, 79, 79) != 0);
183     csd->support_write_block_misalignment = (extract_csd_field(raw_csd, 78, 78) != 0);
184     csd->support_read_block_misalignment = (extract_csd_field(raw_csd, 77, 77) != 0);
185     csd->is_dsr_implemented = (extract_csd_field(raw_csd, 76, 76) != 0);
186 
187     /* TODO */
188     uint32_t c_size = (uint32_t) extract_csd_field(raw_csd, 73, 62);
189     uint32_t c_size_mult = (uint8_t) extract_csd_field(raw_csd, 49, 47);
190 
191     uint32_t num_of_blocks = (c_size + 1U) * (4UL << c_size_mult);
192     csd->device_size_in_bytes = (uint64_t) num_of_blocks * csd->max_read_block_len;
193 
194     csd->read_current_vdd_min = (emmc_csd_vdd_current_min_t) extract_csd_field(raw_csd, 61, 59);
195     csd->read_current_vdd_max = (emmc_csd_vdd_current_max_t) extract_csd_field(raw_csd, 58, 56);
196     csd->write_current_vdd_min = (emmc_csd_vdd_current_min_t) extract_csd_field(raw_csd, 55, 53);
197     csd->write_current_vdd_max = (emmc_csd_vdd_current_max_t) extract_csd_field(raw_csd, 52, 50);
198 
199     uint32_t erase_group_size = extract_csd_field(raw_csd, 46, 42);
200     uint32_t erase_group_multiplier = extract_csd_field(raw_csd, 41, 37);
201     uint32_t wp_group_size = extract_csd_field(raw_csd, 36, 32);
202 
203     /* TODO: check the unit later */
204     csd->erase_group_size = (erase_group_size + 1U) * (erase_group_multiplier + 1U);
205     csd->write_protect_group_size = (1U + wp_group_size) * csd->erase_group_size;
206 
207     csd->is_write_protection_group_enabled = (extract_csd_field(raw_csd, 31, 31) != 0);
208 
209     uint32_t r2w_factor = extract_csd_field(raw_csd, 28, 26);
210     uint32_t write_bl_len = extract_csd_field(raw_csd, 25, 22);
211     csd->max_write_block_len = 1UL << write_bl_len;
212     csd->write_speed_factor = (1U << r2w_factor);
213 
214     csd->support_write_block_partial = (extract_csd_field(raw_csd, 21, 21) != 0);
215     csd->support_content_protect_app = (extract_csd_field(raw_csd, 16, 16) != 0);
216     csd->is_predefined_file_format = (extract_csd_field(raw_csd, 15, 15) != 0);
217     csd->support_copy = (extract_csd_field(raw_csd, 14, 14) != 0);
218     csd->support_permanent_write_protect = (extract_csd_field(raw_csd, 13, 13) != 0);
219     csd->support_temporary_write_protect = (extract_csd_field(raw_csd, 12, 12) != 0);
220 
221     csd->file_format = (uint8_t) extract_csd_field(raw_csd, 11, 10);
222 
223     csd->ecc_type = (uint8_t) extract_csd_field(raw_csd, 9, 8);
224 }
225 
emmc_send_csd(emmc_card_t * card)226 static hpm_stat_t emmc_send_csd(emmc_card_t *card)
227 {
228     sdmmchost_cmd_t *cmd = &card->host->cmd;
229     (void) memset(cmd, 0, sizeof(sdmmchost_cmd_t));
230 
231     cmd->cmd_index = emmc_cmd_send_csd;
232     cmd->cmd_argument = (uint32_t) card->relative_addr << 16;
233     cmd->resp_type = (sdxc_dev_resp_type_t) sdmmc_resp_r2;
234 
235     hpm_stat_t status = emmc_send_cmd(card, cmd);
236     if (status != status_success) {
237         return status;
238     }
239 
240     uint32_t temp_buf[4];
241     memcpy(temp_buf, cmd->response, sizeof(temp_buf));
242     emmc_decode_csd(card, temp_buf);
243 
244     return status_success;
245 }
246 
emmc_get_24bit_num_from_ext_csd(const uint8_t * array)247 static uint32_t emmc_get_24bit_num_from_ext_csd(const uint8_t *array)
248 {
249     uint32_t value = array[0] | (((uint32_t) array[1]) << 8) | (((uint32_t) array[2]) << 16);
250     return value;
251 }
252 
emmc_decode_ext_csd(emmc_card_t * card,emmc_ext_csd_t * ext_csd)253 static hpm_stat_t emmc_decode_ext_csd(emmc_card_t *card, emmc_ext_csd_t *ext_csd)
254 {
255     hpm_stat_t status = status_invalid_argument;
256 
257     do {
258         HPM_BREAK_IF(ext_csd->csd_structure > EMMC_CSD_VERSION_MAX);
259         HPM_BREAK_IF(ext_csd->ext_csd_rev > EMMC_EXT_CSD_REV_MAX);
260         HPM_BREAK_IF(ext_csd->cmd_set_revision > EMMC_CMD_SET_REV_MAX);
261 
262         emmc_device_attribute_t *attr = (emmc_device_attribute_t *) &card->device_attribute;
263 
264         attr->is_secure_write_protection_supported = (
265                 (ext_csd->secure_wp_info & EXT_CSD_SECURE_WP_INFO_SECURE_WP_SUPPORT_MASK) != 0);
266         attr->write_protection_mode = ((ext_csd->secure_wp_info & EXT_CSD_SECURE_WP_INFO_SECURE_WP_EN_STATUS) != 0)
267                                       ? emmc_write_protection_mode_secure : emmc_write_protection_mode_legacy;
268 
269 
270         attr->boot_info.is_alt_boot_mode_supported = IS_HPM_BITMASK_SET(ext_csd->boot_info,
271                                                                         EXT_CSD_BOOT_INFO_ALT_BOOT_MODE_MASK);
272         attr->boot_info.is_ddr_boot_mode_supported = IS_HPM_BITMASK_SET(ext_csd->boot_info,
273                                                                         EXT_CSD_BOOT_INFO_DDR_BOOT_MODE_MASK);
274         attr->boot_info.is_hs_boot_mode_supported = IS_HPM_BITMASK_SET(ext_csd->boot_info,
275                                                                        EXT_CSD_BOOT_INFO_HS_BOOT_MODE_MASK);
276 
277         attr->secure_feature_info.is_secure_erase_supported = IS_HPM_BITMASK_SET(ext_csd->secure_feature_support,
278                                                                                  EXT_CSD_SEC_FEATURE_SUPPORT_SECURE_ER_EN_MASK);
279         attr->secure_feature_info.is_secure_bad_block_management_supported = IS_HPM_BITMASK_SET(
280                 ext_csd->secure_feature_support, EXT_CSD_SEC_FEATURE_SUPPORT_SEC_BD_BLK_EN_MASK);
281         attr->secure_feature_info.is_secure_insecure_trim_supported = IS_HPM_BITMASK_SET(
282                 ext_csd->secure_feature_support, EXT_CSD_SEC_FEATURE_SUPPORT_SEC_GB_CL_EN_MASK);
283         attr->secure_feature_info.is_secure_sanitize_supported = IS_HPM_BITMASK_SET(ext_csd->secure_feature_support,
284                                                                                     EXT_CSD_SEC_FEATURE_SUPPORT_SEC_SANITIZE_MASK);
285 
286         attr->boot_partition_size = SIZE_128KB * ext_csd->boot_partition_size_mult;
287         attr->rpmb_partition_size = SIZE_128KB * ext_csd->rpmb_size;
288 
289         attr->max_enhanced_area_size =
290                 SIZE_512KB * emmc_get_24bit_num_from_ext_csd(ext_csd->enhanced_user_data_area_size);
291 
292         for (uint32_t i = 0; i < 4; i++) {
293             attr->gp_partition_size[i] =
294                     ext_csd->high_capacity_write_protect_group_size * ext_csd->high_capacity_erase_unit_size *
295                     SIZE_512KB * emmc_get_24bit_num_from_ext_csd(ext_csd->general_purpose_partition_size[i]);
296         }
297 
298         attr->max_enhanced_area_size = SIZE_512KB * emmc_get_24bit_num_from_ext_csd(ext_csd->max_enh_size_mult) *
299                                        ext_csd->high_capacity_write_protect_group_size *
300                                        ext_csd->high_capacity_erase_unit_size;
301 
302         attr->super_page_size = 512 * (1UL << (ext_csd->access_size & 0x03));
303         attr->write_protect_group_size =
304                 SIZE_512KB * ext_csd->high_capacity_erase_unit_size * ext_csd->high_capacity_write_protect_group_size;
305         attr->erase_group_size = 512UL * ext_csd->high_capacity_erase_unit_size;
306         attr->device_size_in_bytes = (uint64_t) 512UL * ext_csd->sector_count;
307         attr->sector_count = ext_csd->sector_count;
308         attr->sector_size = (ext_csd->data_sector_size == 0) ? 512U : 4U * SIZE_1KB;
309 
310         attr->device_type.device_type = ext_csd->device_type;
311 
312         attr->large_unit_size = SIZE_1MB * (ext_csd->large_unit_size + 1U);
313         attr->optimal_read_size = 4U * SIZE_1KB * ext_csd->optimal_read_size;
314         attr->optimal_write_size = 4U * SIZE_1KB * ext_csd->optimal_write_size;
315         attr->optimal_trim_unit_size = 4U * SIZE_1KB * (1UL << ext_csd->optimal_trim_unit_size);
316 
317         attr->operation_codes_timeout_us = 100UL * (2U << ext_csd->operation_code_timeout);
318         attr->switch_cmd_timeout_ms = 10UL * ext_csd->generic_cmd6_timeout;
319         attr->power_off_timeout_ms = 10UL * ext_csd->power_off_long_timeout;
320         attr->init_timeout_after_partition_ms = 100UL * ext_csd->init_timeout_after_partitioning;
321         attr->trim_timeout_ms = 300UL * ext_csd->trim_mult;
322         attr->secure_erase_timeout_ms = 300UL * ext_csd->secure_erase_mult;
323         attr->secure_trim_timeout_ms = 300UL * ext_csd->secure_trim_mult;
324 
325         attr->erase_timeout_ms = 300UL * ext_csd->erase_timeout_mult;
326         attr->partition_switch_timeout_ms = 100UL * ext_csd->partition_switch_timing;
327         attr->out_of_interrupt_timeout_ms = 100UL * ext_csd->out_of_interrupt_timing;
328         attr->sleep_notification_timeout_us = 10UL * (2UL << ext_csd->sleep_notification_timeout);
329         attr->sleep_awake_timeout_ns = 100UL * (2UL << ext_csd->sleep_or_awake_timeout);
330         attr->production_state_awareness_timeout_us = 100UL * (2UL << ext_csd->production_state_awareness_timeout);
331 
332         attr->sleep_current_vcc_ua = 2UL << ext_csd->sleep_current_vcc;
333         attr->sleep_current_vccq_ua = 2UL << ext_csd->sleep_current_vccq;
334 
335         attr->use_high_capacity_erase_unit_size = IS_HPM_BITMASK_SET(ext_csd->erase_group_def,
336                                                                      EXT_CSD_ERASE_GROUP_DEF_ENABLE_MASK);
337         attr->is_all_0xffs_for_erased_region = IS_HPM_BITMASK_SET(ext_csd->erased_mem_content, 1);
338         attr->is_enhanced_strobe_supported = IS_HPM_BITMASK_SET(ext_csd->strobe_support, 1);
339         attr->is_cmd_queue_mode_enabled = IS_HPM_BITMASK_SET(ext_csd->cmdq_support, 1);
340 
341         status = status_success;
342 
343     } while (false);
344 
345     return status;
346 }
347 
emmc_send_ext_csd(emmc_card_t * card)348 static hpm_stat_t emmc_send_ext_csd(emmc_card_t *card)
349 {
350     hpm_stat_t status;
351     sdmmchost_cmd_t *cmd = &card->host->cmd;
352     sdmmchost_data_t *data = &card->host->data;
353     sdmmchost_xfer_t *content = &card->host->xfer;
354     memset(cmd, 0, sizeof(*cmd));
355     memset(data, 0, sizeof(*data));
356     memset(content, 0, sizeof(*content));
357     do {
358         cmd->cmd_index = emmc_cmd_send_ext_csd;
359         cmd->resp_type = (sdxc_dev_resp_type_t) sdmmc_resp_r1;
360         cmd->cmd_argument = 0;
361         data->block_size = sizeof(emmc_ext_csd_t);
362         data->block_cnt = 1;
363         data->rx_data = (uint32_t *) sdmmc_get_sys_addr(card->host, (uint32_t) card->host->buffer);
364         content->data = data;
365         content->command = cmd;
366         status = emmc_transfer(card, content);
367         if (status != status_success) {
368             break;
369         }
370 
371         (void) memcpy(&card->ext_csd, card->host->buffer, sizeof(emmc_ext_csd_t));
372 
373         status = emmc_decode_ext_csd(card, &card->ext_csd);
374 
375     } while (false);
376 
377     return status;
378 }
379 
emmc_all_send_cid(emmc_card_t * card)380 static hpm_stat_t emmc_all_send_cid(emmc_card_t *card)
381 {
382     sdmmchost_cmd_t *cmd = &card->host->cmd;
383     (void) memset(cmd, 0, sizeof(sdmmchost_cmd_t));
384 
385     cmd->cmd_index = emmc_cmd_all_send_cid;
386     cmd->resp_type = (sdxc_dev_resp_type_t) sdmmc_resp_r2;
387 
388     hpm_stat_t status = emmc_send_cmd(card, cmd);
389     if (status != status_success) {
390         return status;
391     }
392     for (uint32_t i = 0; i < 3; i++) {
393         card->cid.cid_words[i] = cmd->response[i];
394     }
395 
396     return status;
397 }
398 
emmc_send_cid(emmc_card_t * card)399 hpm_stat_t emmc_send_cid(emmc_card_t *card)
400 {
401     sdmmchost_cmd_t *cmd = &card->host->cmd;
402     (void) memset(cmd, 0, sizeof(sdmmchost_cmd_t));
403 
404     cmd->cmd_index = emmc_cmd_send_cid;
405     cmd->cmd_argument = card->relative_addr << 16;
406     cmd->resp_type = (sdxc_dev_resp_type_t) sdmmc_resp_r2;
407 
408     hpm_stat_t status = emmc_send_cmd(card, cmd);
409     if (status != status_success) {
410         return status;
411     }
412     for (uint32_t i = 0; i < 4; i++) {
413         card->cid.cid_words[i] = cmd->response[i];
414     }
415 
416     return status;
417 }
418 
emmc_set_rca(emmc_card_t * card,uint16_t relative_addr)419 static hpm_stat_t emmc_set_rca(emmc_card_t *card, uint16_t relative_addr)
420 {
421     sdmmchost_cmd_t *cmd = &card->host->cmd;
422     (void) memset(cmd, 0, sizeof(sdmmchost_cmd_t));
423 
424     cmd->cmd_index = emmc_cmd_set_relative_addr;
425     cmd->cmd_argument = relative_addr << 16;
426     cmd->resp_type = (sdxc_dev_resp_type_t) sdmmc_resp_r1;
427 
428     hpm_stat_t status = emmc_send_cmd(card, cmd);
429     if (status != status_success) {
430         return status;
431     }
432     card->relative_addr = relative_addr;
433 
434     return status;
435 }
436 
emmc_error_recovery(emmc_card_t * card)437 static hpm_stat_t emmc_error_recovery(emmc_card_t *card)
438 {
439     sdmmchost_cmd_t *cmd = &card->host->cmd;
440     cmd->cmd_index = sdmmc_cmd_stop_transmission;
441     cmd->cmd_type = sdxc_cmd_type_abort_cmd;
442     cmd->resp_type = (sdxc_dev_resp_type_t) sdmmc_resp_r1b;
443 
444     return sdmmchost_error_recovery(card->host, cmd);
445 }
446 
emmc_check_card_parameters(emmc_card_t * card)447 static hpm_stat_t emmc_check_card_parameters(emmc_card_t *card)
448 {
449     hpm_stat_t status;
450     if ((card == NULL) || (card->host == NULL) || (card->host->host_param.base == NULL)) {
451         status = status_invalid_argument;
452     } else {
453         status = status_success;
454     }
455     return status;
456 }
457 
emmc_set_bus_width(emmc_card_t * card,emmc_bus_mode_t bus_mode)458 static hpm_stat_t emmc_set_bus_width(emmc_card_t *card, emmc_bus_mode_t bus_mode)
459 {
460     emmc_switch_cmd_arg_t switch_arg = {.argument = 0U};
461     switch_arg.access = emmc_switch_cmd_access_mode_write_byte;
462     switch_arg.cmd_set = 0;
463     switch_arg.index = EMMC_EXT_CSD_INDEX_BUS_WDITH;
464     switch_arg.value = (uint8_t) bus_mode;
465 
466     hpm_stat_t status = emmc_switch_function(card, switch_arg, card->device_attribute.switch_cmd_timeout_ms * 1000U);
467 
468     sdmmc_buswidth_t bus_width;
469 
470     if (status == status_success) {
471         switch (bus_mode) {
472         default:
473             bus_width = sdmmc_bus_width_1bit;
474             break;
475         case emmc_bus_mode_x4_sdr:
476         case emmc_bus_mode_x4_ddr:
477             bus_width = sdmmc_bus_width_4bit;
478             break;
479         case emmc_bus_mode_x8_sdr:
480         case emmc_bus_mode_x8_ddr:
481         case emmc_bus_mode_x8_ddr_ds:
482             bus_width = sdmmc_bus_width_8bit;
483             break;
484         }
485         sdmmchost_set_card_bus_width(card->host, bus_width);
486     }
487 
488     return status;
489 }
490 
emmc_set_hs_timing(emmc_card_t * card,emmc_hs_timing_t timing)491 static hpm_stat_t emmc_set_hs_timing(emmc_card_t *card, emmc_hs_timing_t timing)
492 {
493     hpm_stat_t status;
494     uint32_t clock_option;
495 
496     bool clock_inverse = true;
497     sdmmc_speed_mode_t speed;
498     uint32_t timing_val = 0;    /* refer to EXT_CSD[185] for more details */
499     switch (timing) {
500     default:
501         clock_option = MMC_CLOCK_26MHz;
502         speed = sdmmc_emmc_speed_legacy;
503         timing_val = (uint8_t) emmc_timing_legacy;
504         break;
505     case emmc_timing_high_speed:
506         clock_option = MMC_CLOCK_52MHz;
507         speed = sdmmc_emmc_speed_high_speed_sdr;
508         timing_val = (uint8_t) emmc_timing_high_speed;
509         break;
510     case emmc_timing_hs200:
511         clock_option = MMC_CLOCK_HS200;
512         speed = sdmmc_emmc_speed_hs200;
513         timing_val = (uint8_t) emmc_timing_hs200;
514         break;
515     case emmc_timing_hs400:
516         clock_inverse = false;
517         clock_option = MMC_CLOCK_HS400;
518         speed = sdmmc_emmc_speed_hs400;
519         timing_val = (uint8_t) emmc_timing_hs400;
520         break;
521     case emmc_timing_high_speed_ddr:
522         clock_inverse = false;
523         clock_option = MMC_CLOCK_DDR52;
524         speed = sdmmc_emmc_speed_high_speed_ddr;
525         timing_val = (uint8_t) emmc_timing_high_speed;
526         break;
527     }
528 
529     card->current_hs_timing = timing;
530     emmc_switch_cmd_arg_t switch_arg = {.argument = 0U};
531     switch_arg.access = emmc_switch_cmd_access_mode_write_byte;
532     switch_arg.index = EMMC_EXT_CSD_INDEX_HS_TIMING;
533     switch_arg.value = (uint8_t) timing_val;
534     status = emmc_switch_function(card, switch_arg, card->device_attribute.switch_cmd_timeout_ms * 1000U);
535     if (status != status_success) {
536         return status;
537     }
538 
539     sdmmchost_set_speed_mode(card->host, speed);
540     card->host->clock_freq = sdmmchost_set_card_clock(card->host, clock_option, clock_inverse);
541     return status;
542 }
543 
544 void emmc_card_deinit(emmc_card_t *card);
545 
emmc_host_init(emmc_card_t * card)546 hpm_stat_t emmc_host_init(emmc_card_t *card)
547 {
548     hpm_stat_t status = status_success;
549     assert(card != NULL);
550 
551     status = sdmmchost_init(card->host);
552     if (status == status_success) {
553         card->is_host_ready = true;
554     }
555 
556     return status_success;
557 }
558 
emmc_init(emmc_card_t * card)559 hpm_stat_t emmc_init(emmc_card_t *card)
560 {
561     hpm_stat_t status = status_invalid_argument;
562     do {
563         HPM_BREAK_IF(card == NULL);
564         status = emmc_host_init(card);
565         HPM_BREAK_IF(status != status_success);
566         sdmmchost_enable_emmc_support(card->host, true);
567 
568         if (card->host->io_voltage == hpm_sdmmc_io_voltage_3v3) {
569             card->operation_voltage = sdmmc_operation_voltage_3v3;
570         } else {
571             card->operation_voltage = sdmmc_operation_voltage_1v8;
572         }
573 
574         card->host->card_init_done = false;
575         card->relative_addr = 0;
576         card->current_hs_timing = emmc_timing_legacy;
577 
578         card->host->host_param.delay_ms(1); /* Wait a while in case the card connection is still not stable */
579 
580         status = emmc_card_init(card);
581     } while (false);
582 
583     return status;
584 }
585 
emmc_deinit(emmc_card_t * card)586 void emmc_deinit(emmc_card_t *card)
587 {
588     (void) card;
589 }
590 
emmc_probe_device(emmc_card_t * card)591 hpm_stat_t emmc_probe_device(emmc_card_t *card)
592 {
593     hpm_stat_t status = status_invalid_argument;
594 
595     do {
596         status = sdmmc_go_idle_state(card->host, (uint32_t) emmc_idle_option_go_idle_state);
597         HPM_BREAK_IF(status != status_success);
598 
599         emmc_ocr_t ocr = {.ocr_word = 0xc0ff8080};
600 
601         /* Query OCR */
602         status = emmc_send_op_cond(card, ocr);
603         HPM_BREAK_IF(status != status_success);
604         sdmmchost_cmd_t *cmd = &card->host->cmd;
605 
606         emmc_ocr_t recv_ocr = {.ocr_word = 0};
607         do {
608             status = emmc_send_op_cond(card, ocr);
609             HPM_BREAK_IF(status != status_success);
610             recv_ocr.ocr_word = cmd->response[0];
611         } while (recv_ocr.powerup_status == 0);
612 
613         card->ocr.ocr_word = recv_ocr.ocr_word;
614 
615     } while (false);
616 
617     return status;
618 }
619 
emmc_card_init(emmc_card_t * card)620 hpm_stat_t emmc_card_init(emmc_card_t *card)
621 {
622     hpm_stat_t status = emmc_check_card_parameters(card);
623     do {
624         HPM_BREAK_IF(status != status_success);
625 
626         sdmmchost_set_card_bus_width(card->host, sdmmc_bus_width_1bit);
627         sdmmchost_set_card_clock(card->host, SDMMC_CLOCK_400KHZ, true);
628         status = emmc_probe_device(card);
629         HPM_BREAK_IF(status != status_success);
630 
631         card->host->operation_mode = hpm_sdmmc_operation_mode_identification;
632         sdmmchost_init_io(card->host, card->host->operation_mode);
633 
634         card->host->dev_type = sdmmc_dev_type_emmc;
635         sdmmchost_enable_emmc_support(card->host, true);
636 
637         /* Send CMD2 */
638         status = emmc_all_send_cid(card);
639         HPM_BREAK_IF(status != status_success);
640         /* Send CMD3 */
641         status = emmc_set_rca(card, EMMC_RCA_DEFAULT);
642         HPM_BREAK_IF(status != status_success);
643         /* Send CMD9 (SEND_CSD) */
644         status = emmc_send_csd(card);
645         HPM_BREAK_IF(status != status_success);
646 
647         /* Send CMD10 (SEND_CID) */
648         status = emmc_send_cid(card);
649         HPM_BREAK_IF(status != status_success);
650 
651         /* Send CMD7 */
652         status = emmc_select_card(card, true);
653         HPM_BREAK_IF(status != status_success);
654 
655         card->host->operation_mode = hpm_sdmmc_operation_mode_transfer;
656         sdmmchost_init_io(card->host, card->host->operation_mode);
657 
658         sdmmchost_set_card_clock(card->host, SD_CLOCK_25MHZ, true);
659 
660         /*  Send CMD8 */
661         status = emmc_send_ext_csd(card);
662         HPM_BREAK_IF(status != status_success);
663 
664         /* Send CMD16: Set block size */
665         status = sdmmc_set_block_size(card->host, SDMMC_BLOCK_SIZE_DEFAULT);
666         if (status != status_success) {
667             return status;
668         }
669 
670         /***************************************************************************************************************
671          *
672          *      Switch to specified highest frequency
673          *
674          *      Steps:
675          *
676          *      1. Find the allowed maximum speed mode
677          *      2. Switch to the maximum speed mode following the eMMC specification
678          *
679          **************************************************************************************************************/
680         emmc_bus_mode_t bus_mode = emmc_bus_mode_x1_sdr;
681         sdmmc_speed_mode_t speed_mode = sdmmc_emmc_speed_legacy;
682 
683         bool need_switch_to_hs_timing = false;
684         bool need_tuning_in_hs200_mode = false;
685         bool need_enable_enhanced_ds = false;
686 
687         bool support_4bit = IS_HPM_BITMASK_SET(card->host->host_param.host_flags, HPM_SDMMC_HOST_SUPPORT_4BIT);
688         bool support_8bit = IS_HPM_BITMASK_SET(card->host->host_param.host_flags, HPM_SDMMC_HOST_SUPPORT_8BIT);
689         bool support_ddr = IS_HPM_BITMASK_SET(card->host->host_param.host_flags, HPM_SDMMC_HOST_SUPPORT_DDR);
690         bool support_1v8 = IS_HPM_BITMASK_SET(card->host->host_param.host_flags, HPM_SDMMC_HOST_SUPPORT_1V8);
691         bool support_hs200 = support_1v8 && (support_4bit || support_8bit) &&
692                              IS_HPM_BITMASK_SET(card->host->host_param.host_flags, HPM_SDMMC_HOST_SUPPORT_HS200);
693         bool support_hs400 = support_8bit && support_1v8 &&
694                              IS_HPM_BITMASK_SET(card->host->host_param.host_flags, HPM_SDMMC_HOST_SUPPORT_HS400);
695 
696         bool has_configured = false;
697         if (support_4bit) {
698             bus_mode = emmc_bus_mode_x4_sdr;
699         }
700         if (support_8bit) {
701             bus_mode = emmc_bus_mode_x8_sdr;
702         }
703 
704         if (support_hs400 && (card->device_attribute.device_type.support_hs400_at_200mhz_1v8 != 0)) {
705             speed_mode = sdmmc_emmc_speed_hs400;
706             need_switch_to_hs_timing = true;
707             if (card->device_attribute.is_enhanced_strobe_supported != 0U) {
708                 need_enable_enhanced_ds = true;
709                 bus_mode = emmc_bus_mode_x8_ddr_ds;
710             } else {
711                 need_tuning_in_hs200_mode = true;
712                 bus_mode = emmc_bus_mode_x8_ddr;
713             }
714         } else if (support_hs200 && (card->device_attribute.device_type.support_hs200_at_200mhz_1v8 != 0)) {
715             speed_mode = sdmmc_emmc_speed_hs200;
716             need_tuning_in_hs200_mode = true;
717         } else if (support_ddr && (card->device_attribute.device_type.support_high_speed_ddr_at_52mhz_1v8_or_3v != 0)) {
718             speed_mode = sdmmc_emmc_speed_high_speed_ddr;
719             bus_mode = support_8bit ? emmc_bus_mode_x8_ddr : emmc_bus_mode_x4_ddr;
720         } else if (card->device_attribute.device_type.support_high_speed_sdr_at_52mhz) {
721             speed_mode = sdmmc_emmc_speed_high_speed_sdr;
722         } else {
723             speed_mode = sdmmc_emmc_speed_legacy;
724         }
725 
726         /* Perform Tuning procedure for HS200/HS400 without enhanced data strobe */
727         if (need_tuning_in_hs200_mode) {
728             /* Switch to HS200 mode according to eMMC spec */
729             emmc_bus_mode_t expected_mode = support_8bit ? emmc_bus_mode_x8_sdr : emmc_bus_mode_x4_sdr;
730             status = emmc_set_bus_width(card, expected_mode);
731             HPM_BREAK_IF(status != status_success);
732             status = emmc_set_hs_timing(card, emmc_timing_hs200);
733             HPM_BREAK_IF(status != status_success);
734 
735             card->current_hs_timing = emmc_timing_hs200;
736             card->current_bus_mode = expected_mode;
737 
738             /* Perform Tuning process if necessary */
739             status = sdmmc_enable_auto_tuning(card->host);
740             HPM_BREAK_IF(status != status_success);
741 
742             if (speed_mode == sdmmc_emmc_speed_hs200) {
743                 has_configured = true;
744             }
745         }
746 
747         /* Switch to HIGH_SPEED mode first for HS400 mode */
748         if (need_switch_to_hs_timing) {
749             status = emmc_set_hs_timing(card, emmc_timing_high_speed);
750             HPM_BREAK_IF(status != status_success);
751             sdmmchost_set_card_clock(card->host, MMC_CLOCK_26MHz, true);
752         }
753 
754         bool need_manual_set_cardclk_delay_chain = false;
755         emmc_hs_timing_t timing_mode;
756         switch (speed_mode) {
757         case sdmmc_emmc_speed_high_speed_sdr:
758             timing_mode = emmc_timing_high_speed;
759             break;
760         case sdmmc_emmc_speed_high_speed_ddr:
761             timing_mode = emmc_timing_high_speed_ddr;
762             need_manual_set_cardclk_delay_chain = true;
763             break;
764         case sdmmc_emmc_speed_hs200:
765             timing_mode = emmc_timing_hs200;
766             break;
767         case sdmmc_emmc_speed_hs400:
768             timing_mode = emmc_timing_hs400;
769             need_manual_set_cardclk_delay_chain = true;
770             break;
771         default:
772             timing_mode = emmc_timing_legacy;
773             break;
774         }
775 
776         if (!has_configured) {
777             if (timing_mode == emmc_timing_hs400) {
778                 /* Switch BUS mode, then HS_TIMING */
779                 status = emmc_set_bus_width(card, bus_mode);
780                 HPM_BREAK_IF(status != status_success);
781                 status = emmc_set_hs_timing(card, timing_mode);
782                 HPM_BREAK_IF(status != status_success);
783 
784                 if (need_enable_enhanced_ds) {
785                     sdmmchost_enable_enhanced_data_strobe(card->host, true);
786                 }
787                 sdmmchost_set_data_strobe_delay(card->host);
788             } else {
789                 /* Switch HS_TIMING and BUS_WIDTH according to eMMC spec */
790                 status = emmc_set_hs_timing(card, timing_mode);
791                 HPM_BREAK_IF(status != status_success);
792                 status = emmc_set_bus_width(card, bus_mode);
793                 HPM_BREAK_IF(status != status_success);
794             }
795         }
796         card->current_hs_timing = timing_mode;
797         card->current_bus_mode = bus_mode;
798 
799         if (need_manual_set_cardclk_delay_chain) {
800             sdmmchost_set_cardclk_delay_chain(card->host);
801         }
802 
803         /* Delay a while until card switches to the expected timing mode */
804         sdmmchost_delay_ms(card->host, 1U);
805         status = emmc_polling_card_status_busy(card, 10U);
806         card->host->card_init_done = true;
807     } while (false);
808 
809     return status;
810 }
811 
emmc_is_card_present(emmc_card_t * card)812 bool emmc_is_card_present(emmc_card_t *card)
813 {
814     return sdmmchost_is_card_detected(card->host);
815 }
816 
emmc_select_card(emmc_card_t * card,bool is_selected)817 hpm_stat_t emmc_select_card(emmc_card_t *card, bool is_selected)
818 {
819     uint16_t rca = (is_selected) ? card->relative_addr : 0;
820     return sdmmc_select_card(card->host, rca, is_selected);
821 }
822 
emmc_read_blocks(emmc_card_t * card,uint8_t * buffer,uint32_t start_block,uint32_t block_count)823 hpm_stat_t emmc_read_blocks(emmc_card_t *card, uint8_t *buffer, uint32_t start_block, uint32_t block_count)
824 {
825     hpm_stat_t status = emmc_check_card_parameters(card);
826     do {
827         HPM_BREAK_IF(status != status_success);
828 
829         if (!card->host->card_init_done) {
830             status = status_sdmmc_device_init_required;
831             break;
832         }
833 
834         sdmmchost_cmd_t *cmd = &card->host->cmd;
835         sdmmchost_data_t *data = &card->host->data;
836         sdmmchost_xfer_t *content = &card->host->xfer;
837         memset(cmd, 0, sizeof(*cmd));
838         memset(data, 0, sizeof(*data));
839         memset(content, 0, sizeof(*content));
840 
841         while (block_count > 0) {
842             uint32_t read_block_count = (block_count >= MAX_BLOCK_COUNT) ? MAX_BLOCK_COUNT : block_count;
843             if (read_block_count > 1) {
844                 cmd->cmd_index = sdmmc_cmd_read_multiple_block;
845                 data->enable_auto_cmd23 = true;
846             } else {
847                 cmd->cmd_index = sdmmc_cmd_read_single_block;
848             }
849             cmd->resp_type = (sdxc_dev_resp_type_t) sdmmc_resp_r1;
850             cmd->cmd_argument = start_block;
851             data->block_size = SDMMC_BLOCK_SIZE_DEFAULT;
852             data->block_cnt = read_block_count;
853             data->rx_data = (uint32_t *) sdmmc_get_sys_addr(card->host, (uint32_t) buffer);
854             content->data = data;
855             content->command = cmd;
856             uint32_t aligned_start = HPM_L1C_CACHELINE_ALIGN_DOWN((uint32_t) data->rx_data);
857             uint32_t end_addr = (uint32_t) data->rx_data + card->device_attribute.sector_size * block_count;
858             uint32_t aligned_end = HPM_L1C_CACHELINE_ALIGN_UP(end_addr);
859             uint32_t aligned_size = aligned_end - aligned_start;
860             l1c_dc_flush(aligned_start, aligned_size);
861             status = emmc_transfer(card, content);
862             l1c_dc_invalidate(aligned_start, aligned_size);
863             if (status != status_success) {
864                 break;
865             }
866             block_count -= read_block_count;
867             start_block += read_block_count;
868             buffer += SDMMC_BLOCK_SIZE_DEFAULT * read_block_count;
869         }
870     } while (false);
871 
872     return status;
873 }
874 
emmc_write_blocks(emmc_card_t * card,const uint8_t * buffer,uint32_t start_block,uint32_t block_count)875 hpm_stat_t emmc_write_blocks(emmc_card_t *card, const uint8_t *buffer, uint32_t start_block, uint32_t block_count)
876 {
877     hpm_stat_t status = emmc_check_card_parameters(card);
878     do {
879         HPM_BREAK_IF(status != status_success);
880 
881         if (!card->host->card_init_done) {
882             status = status_sdmmc_device_init_required;
883             break;
884         }
885 
886         sdmmchost_cmd_t *cmd = &card->host->cmd;
887         sdmmchost_data_t *data = &card->host->data;
888         sdmmchost_xfer_t *content = &card->host->xfer;
889         memset(cmd, 0, sizeof(*cmd));
890         memset(data, 0, sizeof(*data));
891         memset(content, 0, sizeof(*content));
892 
893         status = emmc_polling_card_status_busy(card, WRITE_BLOCK_TIMEOUT_IN_MS);
894         HPM_BREAK_IF(status != status_success);
895         while (block_count > 0) {
896             uint32_t write_block_count = (block_count >= MAX_BLOCK_COUNT) ? MAX_BLOCK_COUNT : block_count;
897             if (write_block_count > 1) {
898                 cmd->cmd_index = sdmmc_cmd_write_multiple_block;
899                 data->enable_auto_cmd23 = true;
900             } else {
901                 cmd->cmd_index = sdmmc_cmd_write_single_block;
902                 data->enable_auto_cmd12 = false;
903             }
904             cmd->resp_type = (sdxc_dev_resp_type_t) sdmmc_resp_r1;
905             cmd->cmd_argument = start_block;
906             data->block_size = SDMMC_BLOCK_SIZE_DEFAULT;
907             data->block_cnt = write_block_count;
908             data->tx_data = (const uint32_t *) sdmmc_get_sys_addr(card->host, (uint32_t) buffer);
909             content->data = data;
910             content->command = cmd;
911             uint32_t aligned_start = HPM_L1C_CACHELINE_ALIGN_DOWN((uint32_t) data->tx_data);
912             uint32_t aligned_end = HPM_L1C_CACHELINE_ALIGN_UP(
913                     (uint32_t) data->tx_data + card->device_attribute.sector_size * write_block_count);
914             uint32_t aligned_size = aligned_end - aligned_start;
915             l1c_dc_flush(aligned_start, aligned_size);
916             status = emmc_transfer(card, content);
917             if (status != status_success) {
918                 break;
919             }
920             status = emmc_polling_card_status_busy(card, WRITE_BLOCK_TIMEOUT_IN_MS);
921             HPM_BREAK_IF(status != status_success);
922             block_count -= write_block_count;
923             start_block += write_block_count;
924             buffer += SDMMC_BLOCK_SIZE_DEFAULT * write_block_count;
925         }
926 
927     } while (false);
928 
929     return status;
930 }
931 
932 /**
933  * @brief Calculate SD erase timeout value
934  * Refer to SD_Specification_Part1_Physical_Layer_Specification_Version4.20.pdf, section 4.14 for more details.
935  */
emmc_calculate_erase_timeout(emmc_card_t * card,uint32_t start_block,uint32_t block_count)936 static uint32_t emmc_calculate_erase_timeout(emmc_card_t *card, uint32_t start_block, uint32_t block_count)
937 {
938     (void) start_block;
939     uint32_t erase_timeout;
940     if (card->device_attribute.erase_timeout_ms == 0) {
941         erase_timeout = block_count * 250U;
942     } else {
943         erase_timeout = card->device_attribute.erase_timeout_ms;
944     }
945     return erase_timeout;
946 }
947 
emmc_erase_blocks(emmc_card_t * card,uint32_t start_block,uint32_t block_count,emmc_erase_option_t erase_option)948 hpm_stat_t emmc_erase_blocks(emmc_card_t *card,
949                              uint32_t start_block,
950                              uint32_t block_count,
951                              emmc_erase_option_t erase_option)
952 {
953     hpm_stat_t status = emmc_check_card_parameters(card);
954     do {
955         HPM_BREAK_IF(status != status_success);
956 
957         if (!card->host->card_init_done) {
958             status = status_sdmmc_device_init_required;
959             break;
960         }
961 
962         sdmmchost_cmd_t *cmd = &card->host->cmd;
963         memset(cmd, 0, sizeof(*cmd));
964         uint32_t erase_timeout = emmc_calculate_erase_timeout(card, start_block, block_count);
965         /* Send erase start */
966         cmd->cmd_index = emmc_cmd_erase_group_start;
967         cmd->cmd_argument = start_block;
968         cmd->resp_type = (sdxc_dev_resp_type_t) sdmmc_resp_r1;
969         status = emmc_send_cmd(card, cmd);
970         HPM_BREAK_IF(status != status_success);
971         /* Send Erase end */
972         cmd->cmd_index = emmc_cmd_erase_group_end;
973         cmd->cmd_argument = start_block + block_count - 1U;
974         status = emmc_send_cmd(card, cmd);
975         HPM_BREAK_IF(status != status_success);
976 
977         /* Send erase command */
978         uint32_t argument = 0;
979         switch (erase_option) {
980         default:
981             argument = 0;
982             break;
983         case emmc_erase_option_discard:
984             argument = 3;
985             break;
986         case emmc_erase_option_trim:
987             argument = 1;
988             break;
989         }
990         cmd->cmd_index = sdmmc_cmd_erase;
991         cmd->cmd_argument = argument;
992         cmd->resp_type = (sdxc_dev_resp_type_t) sdmmc_resp_r1b;
993         cmd->cmd_timeout_ms = erase_timeout;
994         status = emmc_send_cmd(card, cmd);
995         HPM_BREAK_IF(status != status_success);
996 
997         /* Wait until erase completed. */
998         status = emmc_polling_card_status_busy(card, erase_timeout);
999 
1000     } while (false);
1001 
1002     return status;
1003 }
1004 
emmc_polling_card_status_busy(emmc_card_t * card,uint32_t timeout_ms)1005 hpm_stat_t emmc_polling_card_status_busy(emmc_card_t *card, uint32_t timeout_ms)
1006 {
1007     hpm_stat_t status = status_invalid_argument;
1008     bool is_busy = true;
1009     do {
1010         HPM_BREAK_IF((card == NULL) || (card->host == NULL));
1011 
1012         status = emmc_send_card_status(card);
1013         if (status != status_success) {
1014             break;
1015         }
1016         if ((card->current_r1_status.current_state == sdmmc_state_program) ||
1017             (card->current_r1_status.ready_for_data == 0U)) {
1018             is_busy = true;
1019             card->host->host_param.delay_ms(1);
1020             timeout_ms--;
1021         } else {
1022             is_busy = false;
1023         }
1024 
1025     } while (is_busy && (timeout_ms > 0));
1026 
1027     if ((status == status_success) && is_busy) {
1028         status = status_sdmmc_wait_busy_timeout;
1029     }
1030 
1031     return status;
1032 }
1033 
emmc_switch_function(emmc_card_t * card,emmc_switch_cmd_arg_t arg,uint32_t timeout_us)1034 hpm_stat_t emmc_switch_function(emmc_card_t *card, emmc_switch_cmd_arg_t arg, uint32_t timeout_us)
1035 {
1036     hpm_stat_t error = status_invalid_argument;
1037     do {
1038         HPM_BREAK_IF(card == NULL);
1039 
1040         sdmmchost_cmd_t *cmd = &card->host->cmd;
1041         (void) memset(cmd, 0, sizeof(sdmmchost_cmd_t));
1042 
1043         cmd->cmd_index = emmc_cmd_switch;
1044         cmd->cmd_argument = arg.argument;
1045         cmd->resp_type = (sdxc_dev_resp_type_t) sdmmc_resp_r1b;
1046         cmd->cmd_timeout_ms = (timeout_us + 999) / 1000;
1047         error = emmc_send_cmd(card, cmd);
1048 
1049     } while (false);
1050 
1051     return error;
1052 }
1053