hpm_sdmmc_emmc.c 44 KB

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