sdio_wrapper.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. // SPDX-License-Identifier: Apache-2.0
  2. // Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. #include "esp_log.h"
  16. #include "driver/sdmmc_defs.h"
  17. #include "driver/sdmmc_host.h"
  18. #include "os_wrapper.h"
  19. #include "sdio_reg.h"
  20. #include "sdio_wrapper.h"
  21. #include "esp_hosted_config.h"
  22. DEFINE_LOG_TAG(sdio_wrapper);
  23. #define CIS_BUFFER_SIZE 256
  24. #define FUNC1_EN_MASK (BIT(1))
  25. #define SDIO_INIT_MAX_RETRY 10 // max number of times we try to init SDIO FN 1
  26. #define SDIO_FAIL_IF_NULL(x) do { \
  27. if (!x) return ESP_FAIL; \
  28. } while (0);
  29. #define SDIO_LOCK(x) do { \
  30. if (x) g_h.funcs->_h_lock_mutex(sdio_bus_lock, portMAX_DELAY); \
  31. } while (0);
  32. #define SDIO_UNLOCK(x) do { \
  33. if (x) g_h.funcs->_h_unlock_mutex(sdio_bus_lock); \
  34. } while (0);
  35. static sdmmc_card_t *card = NULL;
  36. static void * sdio_bus_lock;
  37. static esp_err_t hosted_sdio_print_cis_information(sdmmc_card_t* card)
  38. {
  39. uint8_t cis_buffer[CIS_BUFFER_SIZE];
  40. size_t cis_data_len = 1024; //specify maximum searching range to avoid infinite loop
  41. esp_err_t ret = ESP_OK;
  42. SDIO_FAIL_IF_NULL(card);
  43. ret = sdmmc_io_get_cis_data(card, cis_buffer, CIS_BUFFER_SIZE, &cis_data_len);
  44. if (ret == ESP_ERR_INVALID_SIZE) {
  45. int temp_buf_size = cis_data_len;
  46. uint8_t* temp_buf = g_h.funcs->_h_malloc(temp_buf_size);
  47. assert(temp_buf);
  48. ESP_LOGW(TAG, "CIS data longer than expected, temporary buffer allocated.");
  49. ret = sdmmc_io_get_cis_data(card, temp_buf, temp_buf_size, &cis_data_len);
  50. if (ret != ESP_OK) {
  51. ESP_LOGE(TAG, "failed to get CIS data.");
  52. HOSTED_FREE(temp_buf);
  53. return ret;
  54. }
  55. sdmmc_io_print_cis_info(temp_buf, cis_data_len, NULL);
  56. HOSTED_FREE(temp_buf);
  57. } else if (ret == ESP_OK) {
  58. sdmmc_io_print_cis_info(cis_buffer, cis_data_len, NULL);
  59. } else {
  60. ESP_LOGE(TAG, "failed to get CIS data.");
  61. return ret;
  62. }
  63. return ESP_OK;
  64. }
  65. static esp_err_t hosted_sdio_set_blocksize(uint8_t fn, uint16_t value)
  66. {
  67. size_t offset = SD_IO_FBR_START * fn;
  68. const uint8_t *bs_u8 = (const uint8_t *) &value;
  69. uint16_t bs_read = 0;
  70. uint8_t *bs_read_u8 = (uint8_t *) &bs_read;
  71. // Set and read back block size
  72. ESP_ERROR_CHECK(sdmmc_io_write_byte(card, SDIO_FUNC_0, offset + SD_IO_CCCR_BLKSIZEL, bs_u8[0], NULL));
  73. ESP_ERROR_CHECK(sdmmc_io_write_byte(card, SDIO_FUNC_0, offset + SD_IO_CCCR_BLKSIZEH, bs_u8[1], NULL));
  74. ESP_ERROR_CHECK(sdmmc_io_read_byte(card, SDIO_FUNC_0, offset + SD_IO_CCCR_BLKSIZEL, &bs_read_u8[0]));
  75. ESP_ERROR_CHECK(sdmmc_io_read_byte(card, SDIO_FUNC_0, offset + SD_IO_CCCR_BLKSIZEH, &bs_read_u8[1]));
  76. ESP_LOGI(TAG, "Function %d Blocksize: %d", fn, (unsigned int) bs_read);
  77. if (bs_read == value)
  78. return ESP_OK;
  79. else
  80. return ESP_FAIL;
  81. }
  82. static esp_err_t hosted_sdio_card_fn_init(sdmmc_card_t *card)
  83. {
  84. uint8_t ioe = 0;
  85. uint8_t ior = 0;
  86. uint8_t ie = 0;
  87. uint8_t bus_width = 0;
  88. uint16_t bs = 0;
  89. int i = 0;
  90. SDIO_FAIL_IF_NULL(card);
  91. ESP_ERROR_CHECK(sdmmc_io_read_byte(card, SDIO_FUNC_0, SD_IO_CCCR_FN_ENABLE, &ioe));
  92. ESP_LOGD(TAG, "IOE: 0x%02x", ioe);
  93. ESP_ERROR_CHECK(sdmmc_io_read_byte(card, SDIO_FUNC_0, SD_IO_CCCR_FN_READY, &ior));
  94. ESP_LOGD(TAG, "IOR: 0x%02x", ior);
  95. // enable function 1
  96. ioe |= FUNC1_EN_MASK;
  97. ESP_ERROR_CHECK(sdmmc_io_write_byte(card, SDIO_FUNC_0, SD_IO_CCCR_FN_ENABLE, ioe, &ioe));
  98. ESP_LOGD(TAG, "IOE: 0x%02x", ioe);
  99. ESP_ERROR_CHECK(sdmmc_io_read_byte(card, SDIO_FUNC_0, SD_IO_CCCR_FN_ENABLE, &ioe));
  100. ESP_LOGD(TAG, "IOE: 0x%02x", ioe);
  101. // wait for the card to become ready
  102. ior = 0;
  103. for (i = 0; i < SDIO_INIT_MAX_RETRY; i++) {
  104. ESP_ERROR_CHECK(sdmmc_io_read_byte(card, SDIO_FUNC_0, SD_IO_CCCR_FN_READY, &ior));
  105. ESP_LOGD(TAG, "IOR: 0x%02x", ior);
  106. if (ior & FUNC1_EN_MASK) {
  107. break;
  108. } else {
  109. usleep(10 * 1000);
  110. }
  111. }
  112. if (i >= SDIO_INIT_MAX_RETRY) {
  113. // card failed to become ready
  114. return ESP_FAIL;
  115. }
  116. // get interrupt status
  117. ESP_ERROR_CHECK(sdmmc_io_read_byte(card, SDIO_FUNC_0, SD_IO_CCCR_INT_ENABLE, &ie));
  118. ESP_LOGD(TAG, "IE: 0x%02x", ie);
  119. // enable interrupts for function 1 and master enable
  120. ie |= BIT(0) | FUNC1_EN_MASK;
  121. ESP_ERROR_CHECK(sdmmc_io_write_byte(card, SDIO_FUNC_0, SD_IO_CCCR_INT_ENABLE, ie, NULL));
  122. ESP_ERROR_CHECK(sdmmc_io_read_byte(card, SDIO_FUNC_0, SD_IO_CCCR_INT_ENABLE, &ie));
  123. ESP_LOGD(TAG, "IE: 0x%02x", ie);
  124. // get bus width register
  125. ESP_ERROR_CHECK(sdmmc_io_read_byte(card, SDIO_FUNC_0, SD_IO_CCCR_BUS_WIDTH, &bus_width));
  126. ESP_LOGD(TAG, "BUS_WIDTH: 0x%02x", bus_width);
  127. // skip enable of continous SPI interrupts
  128. // set FN0 block size to 512
  129. bs = 512;
  130. ESP_ERROR_CHECK(hosted_sdio_set_blocksize(SDIO_FUNC_0, bs));
  131. // set FN1 block size to 512
  132. bs = 512;
  133. ESP_ERROR_CHECK(hosted_sdio_set_blocksize(SDIO_FUNC_1, bs));
  134. return ESP_OK;
  135. }
  136. static esp_err_t sdio_read_fromio(sdmmc_card_t *card, uint32_t function, uint32_t addr,
  137. uint8_t *data, uint16_t size)
  138. {
  139. uint16_t remainder = size;
  140. uint16_t blocks;
  141. esp_err_t res;
  142. uint8_t *ptr = data;
  143. // do block mode transfer
  144. while (remainder >= ESP_BLOCK_SIZE) {
  145. blocks = H_SDIO_RX_BLOCKS_TO_TRANSFER(remainder);
  146. size = blocks * ESP_BLOCK_SIZE;
  147. res = sdmmc_io_read_blocks(card, function, addr, ptr, size);
  148. if (res)
  149. return res;
  150. remainder -= size;
  151. ptr += size;
  152. addr += size;
  153. }
  154. // transfer remainder using byte mode
  155. while (remainder > 0) {
  156. size = remainder;
  157. res = sdmmc_io_read_bytes(card, function, addr, ptr, size);
  158. if (res)
  159. return res;
  160. remainder -= size;
  161. ptr += size;
  162. addr += size;
  163. }
  164. return ESP_OK;
  165. }
  166. static esp_err_t sdio_write_toio(sdmmc_card_t *card, uint32_t function, uint32_t addr,
  167. uint8_t *data, uint16_t size)
  168. {
  169. uint16_t remainder = size;
  170. uint16_t blocks;
  171. esp_err_t res;
  172. uint8_t *ptr = data;
  173. // do block mode transfer
  174. while (remainder >= ESP_BLOCK_SIZE) {
  175. blocks = H_SDIO_TX_BLOCKS_TO_TRANSFER(remainder);
  176. size = blocks * ESP_BLOCK_SIZE;
  177. res = sdmmc_io_write_blocks(card, function, addr, ptr, size);
  178. if (res)
  179. return res;
  180. remainder -= size;
  181. ptr += size;
  182. addr += size;
  183. }
  184. // transfer remainder using byte mode
  185. while (remainder > 0) {
  186. size = remainder;
  187. res = sdmmc_io_write_bytes(card, function, addr, ptr, size);
  188. if (res)
  189. return res;
  190. remainder -= size;
  191. ptr += size;
  192. addr += size;
  193. }
  194. return ESP_OK;
  195. }
  196. void * hosted_sdio_init(void)
  197. {
  198. esp_err_t res;
  199. sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
  200. // initialise SDMMC host
  201. res = sdmmc_host_init();
  202. if (res != ESP_OK)
  203. return NULL;
  204. // configure SDIO interface and slot
  205. slot_config.width = H_SDIO_BUS_WIDTH;
  206. #if defined(H_SDIO_SOC_USE_GPIO_MATRIX)
  207. slot_config.clk = H_SDIO_PIN_CLK;
  208. slot_config.cmd = H_SDIO_PIN_CMD;
  209. slot_config.d0 = H_SDIO_PIN_D0;
  210. slot_config.d1 = H_SDIO_PIN_D1;
  211. #if (H_SDIO_BUS_WIDTH == 4)
  212. slot_config.d2 = H_SDIO_PIN_D2;
  213. slot_config.d3 = H_SDIO_PIN_D3;
  214. #endif
  215. #endif
  216. res = sdmmc_host_init_slot(H_SDMMC_HOST_SLOT, &slot_config);
  217. if (res != ESP_OK) {
  218. ESP_LOGE(TAG, "init SDMMC Host slot %d failed", H_SDMMC_HOST_SLOT);
  219. return NULL;
  220. }
  221. // initialise connected SDIO card/slave
  222. card = (sdmmc_card_t *)g_h.funcs->_h_malloc(sizeof(sdmmc_card_t));
  223. if (!card)
  224. return NULL;
  225. // initialise mutex for bus locking
  226. sdio_bus_lock = g_h.funcs->_h_create_mutex();
  227. assert(sdio_bus_lock);
  228. return (void *)card;
  229. }
  230. int hosted_sdio_card_init(void *ctx)
  231. {
  232. sdmmc_host_t config = SDMMC_HOST_DEFAULT();
  233. if (H_SDIO_BUS_WIDTH == 4)
  234. config.flags = SDMMC_HOST_FLAG_4BIT;
  235. else
  236. config.flags = SDMMC_HOST_FLAG_1BIT;
  237. config.max_freq_khz = H_SDIO_CLOCK_FREQ_KHZ;
  238. ESP_LOGI(TAG, "SDIO master: Data-Lines: %d-bit Freq(KHz)[%u KHz]", H_SDIO_BUS_WIDTH==4? 4:1,
  239. config.max_freq_khz);
  240. #if (H_SDIO_BUS_WIDTH == 4)
  241. ESP_LOGI(TAG, "GPIOs: CLK[%u] CMD[%u] D0[%u] D1[%u] D2[%u] D3[%u] Slave_Reset[%u]",
  242. CONFIG_ESP_SDIO_PIN_CLK, CONFIG_ESP_SDIO_PIN_CMD,
  243. CONFIG_ESP_SDIO_PIN_D0, CONFIG_ESP_SDIO_PIN_D1,
  244. CONFIG_ESP_SDIO_PIN_D2, CONFIG_ESP_SDIO_PIN_D3,
  245. CONFIG_ESP_GPIO_SLAVE_RESET_SLAVE);
  246. #else
  247. ESP_LOGI(TAG, "GPIOs: CLK[%u] CMD[%u] D0[%u] D1[%u] Slave_Reset[%u]",
  248. CONFIG_ESP_SDIO_PIN_CLK, CONFIG_ESP_SDIO_PIN_CMD,
  249. CONFIG_ESP_SDIO_PIN_D0, CONFIG_ESP_SDIO_PIN_D1,
  250. CONFIG_ESP_GPIO_SLAVE_RESET_SLAVE);
  251. #endif
  252. ESP_LOGI(TAG, "Queues: Tx[%u] Rx[%u] SDIO-Rx-Mode[%u]",
  253. CONFIG_ESP_SDIO_TX_Q_SIZE, CONFIG_ESP_SDIO_RX_Q_SIZE,
  254. H_SDIO_HOST_RX_MODE);
  255. #ifdef CONFIG_IDF_TARGET_ESP32P4
  256. // Set this flag to allocate aligned buffer of 512 bytes to meet
  257. // DMA's requirements for CMD53 byte mode. Mandatory when any
  258. // buffer is behind the cache, or not aligned to 4 byte boundary.
  259. config.flags |= SDMMC_HOST_FLAG_ALLOC_ALIGNED_BUF;
  260. #endif
  261. if (sdmmc_card_init(&config, card) != ESP_OK) {
  262. ESP_LOGE(TAG, "sdmmc_card_init failed");
  263. goto fail;
  264. }
  265. // output CIS info from the slave
  266. sdmmc_card_print_info(stdout, card);
  267. if (hosted_sdio_print_cis_information(card) != ESP_OK) {
  268. ESP_LOGW(TAG, "failed to print card info");
  269. }
  270. // initialise the card functions
  271. if (hosted_sdio_card_fn_init(card) != ESP_OK) {
  272. ESP_LOGE(TAG, "sdio_cared_fn_init failed");
  273. goto fail;
  274. }
  275. return ESP_OK;
  276. fail:
  277. sdmmc_host_deinit();
  278. if (card) {
  279. HOSTED_FREE(card);
  280. }
  281. return ESP_FAIL;
  282. }
  283. esp_err_t hosted_sdio_deinit(void *ctx)
  284. {
  285. sdmmc_card_t *card = (sdmmc_card_t*) ctx;
  286. if (card) {
  287. sdmmc_host_deinit();
  288. HOSTED_FREE(card);
  289. return ESP_OK;
  290. }
  291. return ESP_FAIL;
  292. }
  293. int hosted_sdio_read_reg(uint32_t reg, uint8_t *data, uint16_t size, bool lock_required)
  294. {
  295. int res = 0;
  296. SDIO_FAIL_IF_NULL(card);
  297. /* Need to apply address mask when reading/writing slave registers */
  298. reg &= ESP_ADDRESS_MASK;
  299. SDIO_LOCK(lock_required);
  300. if (size <= 1) {
  301. res = sdmmc_io_read_byte(card, SDIO_FUNC_1, reg, data);
  302. } else {
  303. res = sdmmc_io_read_bytes(card, SDIO_FUNC_1, reg, data, size);
  304. }
  305. SDIO_UNLOCK(lock_required);
  306. return res;
  307. }
  308. int hosted_sdio_write_reg(uint32_t reg, uint8_t *data, uint16_t size, bool lock_required)
  309. {
  310. int res = 0;
  311. SDIO_FAIL_IF_NULL(card);
  312. /* Need to apply address mask when reading/writing slave registers */
  313. reg &= ESP_ADDRESS_MASK;
  314. SDIO_LOCK(lock_required);
  315. if (size <= 1) {
  316. res = sdmmc_io_write_byte(card, SDIO_FUNC_1, reg, *data, NULL);
  317. } else {
  318. res = sdmmc_io_write_bytes(card, SDIO_FUNC_1, reg, data, size);
  319. }
  320. SDIO_UNLOCK(lock_required);
  321. return res;
  322. }
  323. int hosted_sdio_read_block(uint32_t reg, uint8_t *data, uint16_t size, bool lock_required)
  324. {
  325. int res = 0;
  326. SDIO_FAIL_IF_NULL(card);
  327. SDIO_LOCK(lock_required);
  328. if (size <= 1) {
  329. res = sdmmc_io_read_byte(card, SDIO_FUNC_1, reg, data);
  330. } else {
  331. res = sdio_read_fromio(card, SDIO_FUNC_1, reg, data, H_SDIO_RX_LEN_TO_TRANSFER(size));
  332. }
  333. SDIO_UNLOCK(lock_required);
  334. return res;
  335. }
  336. int hosted_sdio_write_block(uint32_t reg, uint8_t *data, uint16_t size, bool lock_required)
  337. {
  338. int res = 0;
  339. SDIO_FAIL_IF_NULL(card);
  340. SDIO_LOCK(lock_required);
  341. if (size <= 1) {
  342. res = sdmmc_io_write_byte(card, SDIO_FUNC_1, reg, *data, NULL);
  343. } else {
  344. res = sdio_write_toio(card, SDIO_FUNC_1, reg, data, H_SDIO_TX_LEN_TO_TRANSFER(size));
  345. }
  346. SDIO_UNLOCK(lock_required);
  347. return res;
  348. }
  349. /* Blocking fn call. Returns when SDIO slave device generates a SDIO interupt */
  350. int hosted_sdio_wait_slave_intr(uint32_t ticks_to_wait)
  351. {
  352. SDIO_FAIL_IF_NULL(card);
  353. return sdmmc_io_wait_int(card, ticks_to_wait);
  354. }