block_dev.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. #include <string.h>
  2. #include "FreeRTOS.h"
  3. #include "trace.h"
  4. #include "mmcsd_core.h"
  5. #define SECTOR_SIZE 512
  6. int32_t mmcsd_num_wr_blocks(struct mmcsd_card *card)
  7. {
  8. int32_t err;
  9. uint32_t blocks;
  10. struct mmcsd_req req;
  11. struct mmcsd_cmd cmd;
  12. struct mmcsd_data data;
  13. uint32_t timeout_us;
  14. memset(&cmd, 0, sizeof(struct mmcsd_cmd));
  15. cmd.cmd_code = APP_CMD;
  16. cmd.arg = card->rca << 16;
  17. cmd.flags = RESP_SPI_R1 | RESP_R1 | CMD_AC;
  18. err = mmcsd_send_cmd(card->host, &cmd, 0);
  19. if (err)
  20. return -1;
  21. if (!controller_is_spi(card->host) && !(cmd.resp[0] & R1_APP_CMD))
  22. return -1;
  23. memset(&cmd, 0, sizeof(struct mmcsd_cmd));
  24. cmd.cmd_code = SD_APP_SEND_NUM_WR_BLKS;
  25. cmd.arg = 0;
  26. cmd.flags = RESP_SPI_R1 | RESP_R1 | CMD_ADTC;
  27. memset(&data, 0, sizeof(struct mmcsd_data));
  28. data.timeout_ns = card->tacc_ns * 100;
  29. data.timeout_clks = card->tacc_clks * 100;
  30. timeout_us = data.timeout_ns / 1000;
  31. timeout_us += data.timeout_clks * 1000 /
  32. (card->host->io_cfg.clock / 1000);
  33. if (timeout_us > 100000)
  34. {
  35. data.timeout_ns = 100000000;
  36. data.timeout_clks = 0;
  37. }
  38. data.blksize = 4;
  39. data.blks = 1;
  40. data.flags = DATA_DIR_READ;
  41. data.buf = &blocks;
  42. memset(&req, 0, sizeof(struct mmcsd_req));
  43. req.cmd = &cmd;
  44. req.data = &data;
  45. mmcsd_send_request(card->host, &req);
  46. if (cmd.err || data.err)
  47. return -1;
  48. return blocks;
  49. }
  50. int mmcsd_req_blk(struct mmcsd_card *card,
  51. uint32_t sector,
  52. void *buf,
  53. size_t blks,
  54. uint8_t dir)
  55. {
  56. struct mmcsd_cmd cmd, stop;
  57. struct mmcsd_data data;
  58. struct mmcsd_req req;
  59. struct mmcsd_host *host = card->host;
  60. uint32_t r_cmd, w_cmd;
  61. mmcsd_host_lock(host);
  62. memset(&req, 0, sizeof(struct mmcsd_req));
  63. memset(&cmd, 0, sizeof(struct mmcsd_cmd));
  64. memset(&stop, 0, sizeof(struct mmcsd_cmd));
  65. memset(&data, 0, sizeof(struct mmcsd_data));
  66. req.cmd = &cmd;
  67. req.data = &data;
  68. cmd.arg = sector;
  69. if (!(card->flags & CARD_FLAG_SDHC))
  70. {
  71. cmd.arg <<= 9;
  72. }
  73. cmd.flags = RESP_SPI_R1 | RESP_R1 | CMD_ADTC;
  74. data.blksize = SECTOR_SIZE;
  75. data.blks = blks;
  76. if (blks > 1)
  77. {
  78. if (!controller_is_spi(card->host) || !dir)
  79. {
  80. req.stop = &stop;
  81. stop.cmd_code = STOP_TRANSMISSION;
  82. stop.arg = 0;
  83. stop.flags = RESP_SPI_R1B | RESP_R1B | CMD_AC;
  84. }
  85. r_cmd = READ_MULTIPLE_BLOCK;
  86. w_cmd = WRITE_MULTIPLE_BLOCK;
  87. }
  88. else
  89. {
  90. req.stop = NULL;
  91. r_cmd = READ_SINGLE_BLOCK;
  92. w_cmd = WRITE_BLOCK;
  93. }
  94. if (!dir)
  95. {
  96. cmd.cmd_code = r_cmd;
  97. data.flags |= DATA_DIR_READ;
  98. }
  99. else
  100. {
  101. cmd.cmd_code = w_cmd;
  102. data.flags |= DATA_DIR_WRITE;
  103. }
  104. mmcsd_set_data_timeout(&data, card);
  105. data.buf = buf;
  106. mmcsd_send_request(host, &req);
  107. if (!controller_is_spi(card->host) && dir != 0)
  108. {
  109. do
  110. {
  111. int32_t err;
  112. cmd.cmd_code = SEND_STATUS;
  113. cmd.arg = card->rca << 16;
  114. cmd.flags = RESP_R1 | CMD_AC;
  115. err = mmcsd_send_cmd(card->host, &cmd, 5);
  116. if (err)
  117. {
  118. TRACE_ERROR("error %d requesting status", err);
  119. break;
  120. }
  121. /*
  122. * Some cards mishandle the status bits,
  123. * so make sure to check both the busy
  124. * indication and the card state.
  125. */
  126. } while (!(cmd.resp[0] & R1_READY_FOR_DATA) ||
  127. (R1_CURRENT_STATE(cmd.resp[0]) == 7));
  128. }
  129. mmcsd_host_unlock(host);
  130. if (cmd.err || data.err || stop.err)
  131. {
  132. TRACE_ERROR("mmcsd request blocks error");
  133. TRACE_ERROR("%d,%d,%d, 0x%08x,0x%08x",
  134. cmd.err, data.err, stop.err, data.flags, sector);
  135. return -1;
  136. }
  137. return 0;
  138. }
  139. int32_t mmcsd_set_blksize(struct mmcsd_card *card)
  140. {
  141. struct mmcsd_cmd cmd;
  142. int err;
  143. /* Block-addressed cards ignore MMC_SET_BLOCKLEN. */
  144. if (card->flags & CARD_FLAG_SDHC)
  145. return 0;
  146. mmcsd_host_lock(card->host);
  147. cmd.cmd_code = SET_BLOCKLEN;
  148. cmd.arg = 512;
  149. cmd.flags = RESP_SPI_R1 | RESP_R1 | CMD_AC;
  150. err = mmcsd_send_cmd(card->host, &cmd, 5);
  151. mmcsd_host_unlock(card->host);
  152. if (err)
  153. {
  154. TRACE_ERROR("MMCSD: unable to set block size to %d: %d", cmd.arg, err);
  155. return -1;
  156. }
  157. return 0;
  158. }