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