sdmmc_common.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /*
  2. * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
  3. * Adaptations to ESP-IDF Copyright (c) 2016-2018 Espressif Systems (Shanghai) PTE LTD
  4. *
  5. * Permission to use, copy, modify, and distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  15. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. #pragma once
  18. #include <string.h>
  19. #include "esp_log.h"
  20. #include "esp_heap_caps.h"
  21. #include "freertos/FreeRTOS.h"
  22. #include "freertos/task.h"
  23. #include "driver/sdmmc_defs.h"
  24. #include "driver/sdmmc_types.h"
  25. #include "sdmmc_cmd.h"
  26. #include "sys/param.h"
  27. #include "soc/soc_memory_layout.h"
  28. #define SDMMC_GO_IDLE_DELAY_MS 20
  29. #define SDMMC_IO_SEND_OP_COND_DELAY_MS 10
  30. /* These delay values are mostly useful for cases when CD pin is not used, and
  31. * the card is removed. In this case, SDMMC peripheral may not always return
  32. * CMD_DONE / DATA_DONE interrupts after signaling the error. These timeouts work
  33. * as a safety net in such cases.
  34. */
  35. #define SDMMC_DEFAULT_CMD_TIMEOUT_MS 1000 // Max timeout of ordinary commands
  36. #define SDMMC_WRITE_CMD_TIMEOUT_MS 5000 // Max timeout of write commands
  37. #define SDMMC_SD_DISCARD_TIMEOUT 250 // SD erase (discard) timeout
  38. /* Maximum retry/error count for SEND_OP_COND (CMD1).
  39. * These are somewhat arbitrary, values originate from OpenBSD driver.
  40. */
  41. #define SDMMC_SEND_OP_COND_MAX_RETRIES 100
  42. #define SDMMC_SEND_OP_COND_MAX_ERRORS 3
  43. /* supported arguments for erase command 38 */
  44. #define SDMMC_SD_ERASE_ARG 0
  45. #define SDMMC_SD_DISCARD_ARG 1
  46. #define SDMMC_MMC_TRIM_ARG 1
  47. #define SDMMC_MMC_DISCARD_ARG 3
  48. /* Functions to send individual commands */
  49. esp_err_t sdmmc_send_cmd(sdmmc_card_t* card, sdmmc_command_t* cmd);
  50. esp_err_t sdmmc_send_app_cmd(sdmmc_card_t* card, sdmmc_command_t* cmd);
  51. esp_err_t sdmmc_send_cmd_go_idle_state(sdmmc_card_t* card);
  52. esp_err_t sdmmc_send_cmd_send_if_cond(sdmmc_card_t* card, uint32_t ocr);
  53. esp_err_t sdmmc_send_cmd_send_op_cond(sdmmc_card_t* card, uint32_t ocr, uint32_t *ocrp);
  54. esp_err_t sdmmc_send_cmd_read_ocr(sdmmc_card_t *card, uint32_t *ocrp);
  55. esp_err_t sdmmc_send_cmd_send_cid(sdmmc_card_t *card, sdmmc_cid_t *out_cid);
  56. esp_err_t sdmmc_send_cmd_all_send_cid(sdmmc_card_t* card, sdmmc_response_t* out_raw_cid);
  57. esp_err_t sdmmc_send_cmd_set_relative_addr(sdmmc_card_t* card, uint16_t* out_rca);
  58. esp_err_t sdmmc_send_cmd_set_blocklen(sdmmc_card_t* card, sdmmc_csd_t* csd);
  59. esp_err_t sdmmc_send_cmd_switch_func(sdmmc_card_t* card,
  60. uint32_t mode, uint32_t group, uint32_t function,
  61. sdmmc_switch_func_rsp_t* resp);
  62. esp_err_t sdmmc_send_cmd_send_csd(sdmmc_card_t* card, sdmmc_csd_t* out_csd);
  63. esp_err_t sdmmc_send_cmd_select_card(sdmmc_card_t* card, uint32_t rca);
  64. esp_err_t sdmmc_send_cmd_send_scr(sdmmc_card_t* card, sdmmc_scr_t *out_scr);
  65. esp_err_t sdmmc_send_cmd_set_bus_width(sdmmc_card_t* card, int width);
  66. esp_err_t sdmmc_send_cmd_send_status(sdmmc_card_t* card, uint32_t* out_status);
  67. esp_err_t sdmmc_send_cmd_crc_on_off(sdmmc_card_t* card, bool crc_enable);
  68. /* Higher level functions */
  69. esp_err_t sdmmc_enable_hs_mode(sdmmc_card_t* card);
  70. esp_err_t sdmmc_enable_hs_mode_and_check(sdmmc_card_t* card);
  71. esp_err_t sdmmc_write_sectors_dma(sdmmc_card_t* card, const void* src,
  72. size_t start_block, size_t block_count);
  73. esp_err_t sdmmc_read_sectors_dma(sdmmc_card_t* card, void* dst,
  74. size_t start_block, size_t block_count);
  75. uint32_t sdmmc_get_erase_timeout_ms(const sdmmc_card_t* card, int arg, size_t erase_size_kb);
  76. /* SD specific */
  77. esp_err_t sdmmc_check_scr(sdmmc_card_t* card);
  78. esp_err_t sdmmc_decode_cid(sdmmc_response_t resp, sdmmc_cid_t* out_cid);
  79. esp_err_t sdmmc_decode_csd(sdmmc_response_t response, sdmmc_csd_t* out_csd);
  80. esp_err_t sdmmc_decode_scr(uint32_t *raw_scr, sdmmc_scr_t* out_scr);
  81. esp_err_t sdmmc_decode_ssr(uint32_t *raw_ssr, sdmmc_ssr_t* out_ssr);
  82. uint32_t sdmmc_sd_get_erase_timeout_ms(const sdmmc_card_t* card, int arg, size_t erase_size_kb);
  83. /* SDIO specific */
  84. esp_err_t sdmmc_io_reset(sdmmc_card_t* card);
  85. esp_err_t sdmmc_io_enable_hs_mode(sdmmc_card_t* card);
  86. esp_err_t sdmmc_io_send_op_cond(sdmmc_card_t* card, uint32_t ocr, uint32_t *ocrp);
  87. esp_err_t sdmmc_io_rw_direct(sdmmc_card_t* card, int function,
  88. uint32_t reg, uint32_t arg, uint8_t *byte);
  89. esp_err_t sdmmc_io_rw_extended(sdmmc_card_t* card, int function,
  90. uint32_t reg, int arg, void *data, size_t size);
  91. /* MMC specific */
  92. esp_err_t sdmmc_mmc_send_ext_csd_data(sdmmc_card_t* card, void *out_data, size_t datalen);
  93. esp_err_t sdmmc_mmc_switch(sdmmc_card_t* card, uint8_t set, uint8_t index, uint8_t value);
  94. esp_err_t sdmmc_mmc_decode_cid(int mmc_ver, sdmmc_response_t resp, sdmmc_cid_t* out_cid);
  95. esp_err_t sdmmc_mmc_decode_csd(sdmmc_response_t response, sdmmc_csd_t* out_csd);
  96. esp_err_t sdmmc_mmc_enable_hs_mode(sdmmc_card_t* card);
  97. uint32_t sdmmc_mmc_get_erase_timeout_ms(const sdmmc_card_t* card, int arg, size_t erase_size_kb);
  98. /* Parts of card initialization flow */
  99. esp_err_t sdmmc_init_sd_if_cond(sdmmc_card_t* card);
  100. esp_err_t sdmmc_init_select_card(sdmmc_card_t* card);
  101. esp_err_t sdmmc_init_csd(sdmmc_card_t* card);
  102. esp_err_t sdmmc_init_cid(sdmmc_card_t* card);
  103. esp_err_t sdmmc_init_rca(sdmmc_card_t* card);
  104. esp_err_t sdmmc_init_mmc_decode_cid(sdmmc_card_t* card);
  105. esp_err_t sdmmc_init_ocr(sdmmc_card_t* card);
  106. esp_err_t sdmmc_init_spi_crc(sdmmc_card_t* card);
  107. esp_err_t sdmmc_init_io(sdmmc_card_t* card);
  108. esp_err_t sdmmc_init_sd_blocklen(sdmmc_card_t* card);
  109. esp_err_t sdmmc_init_sd_scr(sdmmc_card_t* card);
  110. esp_err_t sdmmc_init_sd_ssr(sdmmc_card_t* card);
  111. esp_err_t sdmmc_init_sd_wait_data_ready(sdmmc_card_t* card);
  112. esp_err_t sdmmc_init_mmc_read_ext_csd(sdmmc_card_t* card);
  113. esp_err_t sdmmc_init_mmc_read_cid(sdmmc_card_t* card);
  114. esp_err_t sdmmc_init_host_bus_width(sdmmc_card_t* card);
  115. esp_err_t sdmmc_init_sd_bus_width(sdmmc_card_t* card);
  116. esp_err_t sdmmc_init_io_bus_width(sdmmc_card_t* card);
  117. esp_err_t sdmmc_init_mmc_bus_width(sdmmc_card_t* card);
  118. esp_err_t sdmmc_init_card_hs_mode(sdmmc_card_t* card);
  119. esp_err_t sdmmc_init_host_frequency(sdmmc_card_t* card);
  120. esp_err_t sdmmc_init_mmc_check_ext_csd(sdmmc_card_t* card);
  121. /* Various helper functions */
  122. static inline bool host_is_spi(const sdmmc_card_t* card)
  123. {
  124. return (card->host.flags & SDMMC_HOST_FLAG_SPI) != 0;
  125. }
  126. static inline uint32_t get_host_ocr(float voltage)
  127. {
  128. // TODO: report exact voltage to the card
  129. // For now tell that the host has 2.8-3.6V voltage range
  130. (void) voltage;
  131. return SD_OCR_VOL_MASK;
  132. }
  133. void sdmmc_flip_byte_order(uint32_t* response, size_t size);
  134. esp_err_t sdmmc_fix_host_flags(sdmmc_card_t* card);