hpm_sdmmc_sd.c 41 KB

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