fsdio_cmd.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. * Copyright : (C) 2022 Phytium Information Technology, Inc.
  3. * All Rights Reserved.
  4. *
  5. * This program is OPEN SOURCE software: you can redistribute it and/or modify it
  6. * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
  7. * either version 1.0 of the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
  10. * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. * See the Phytium Public License for more details.
  12. *
  13. *
  14. * FilePath: fsdio_cmd.c
  15. * Date: 2022-06-01 14:23:59
  16. * LastEditTime: 2022-06-01 14:24:00
  17. * Description:  This files is for SDIO command related function
  18. *
  19. * Modify History:
  20. * Ver   Who        Date         Changes
  21. * ----- ------     --------    --------------------------------------
  22. * 1.1 zhugengyu 2022/6/6 modify according to tech manual.
  23. */
  24. /***************************** Include Files *********************************/
  25. #include "fio.h"
  26. #include "fdebug.h"
  27. #include "fassert.h"
  28. #include "ftypes.h"
  29. #include "fcache.h"
  30. #include "fsdio_hw.h"
  31. #include "fsdio.h"
  32. /************************** Constant Definitions *****************************/
  33. /**************************** Type Definitions *******************************/
  34. /***************** Macros (Inline Functions) Definitions *********************/
  35. #define FSDIO_DEBUG_TAG "FSDIO-CMD"
  36. #define FSDIO_ERROR(format, ...) FT_DEBUG_PRINT_E(FSDIO_DEBUG_TAG, format, ##__VA_ARGS__)
  37. #define FSDIO_WARN(format, ...) FT_DEBUG_PRINT_W(FSDIO_DEBUG_TAG, format, ##__VA_ARGS__)
  38. #define FSDIO_INFO(format, ...) FT_DEBUG_PRINT_I(FSDIO_DEBUG_TAG, format, ##__VA_ARGS__)
  39. #define FSDIO_DEBUG(format, ...) FT_DEBUG_PRINT_D(FSDIO_DEBUG_TAG, format, ##__VA_ARGS__)
  40. /************************** Function Prototypes ******************************/
  41. extern FError FSdioPIOReadData(FSdio *const instance_p, FSdioData *data_p);
  42. /*****************************************************************************/
  43. FError FSdioSendPrivateCmd(uintptr base_addr, u32 cmd, u32 arg)
  44. {
  45. u32 reg_val;
  46. int retries = FSDIO_TIMEOUT;
  47. do
  48. {
  49. reg_val = FSDIO_READ_REG(base_addr, FSDIO_STATUS_OFFSET);
  50. if (--retries <= 0)
  51. break;
  52. }
  53. while (FSDIO_STATUS_DATA_BUSY & reg_val);
  54. if (retries <= 0)
  55. return FSDIO_ERR_BUSY;
  56. FSDIO_WRITE_REG(base_addr, FSDIO_CMD_ARG_OFFSET, arg);
  57. FSDIO_WRITE_REG(base_addr, FSDIO_CMD_OFFSET, FSDIO_CMD_START | cmd);
  58. retries = FSDIO_TIMEOUT;
  59. do
  60. {
  61. reg_val = FSDIO_READ_REG(base_addr, FSDIO_CMD_OFFSET);
  62. if (--retries <= 0)
  63. break;
  64. }
  65. while (FSDIO_CMD_START & reg_val);
  66. return (retries <= 0) ? FSDIO_ERR_TIMEOUT : FSDIO_SUCCESS;
  67. }
  68. /**
  69. * @name: FSdioTransferCmd
  70. * @msg: pack and transfer command
  71. * @return {FError} FSDIO_SUCCESS if transfer success
  72. * @param {FSdio} *instance_p, SDIO controller instance
  73. * @param {FSdioCmdData} *cmd_data_p, contents of transfer command and data
  74. */
  75. FError FSdioTransferCmd(FSdio *const instance_p, FSdioCmdData *const cmd_data_p)
  76. {
  77. FASSERT(cmd_data_p);
  78. FError ret = FSDIO_SUCCESS;
  79. uintptr base_addr = instance_p->config.base_addr;
  80. u32 cmd_flag = cmd_data_p->flag;
  81. u32 raw_cmd = FSDIO_CMD_USE_HOLD_REG; /* USE_HOLD_REG必须为1 */
  82. /* 命令需要进行卡初始化,如CMD-0 */
  83. if (FSDIO_CMD_FLAG_NEED_INIT & cmd_flag)
  84. {
  85. raw_cmd |= FSDIO_CMD_INIT;
  86. }
  87. /* 命令涉及电压切换 */
  88. if (FSDIO_CMD_FLAG_SWITCH_VOLTAGE & cmd_flag)
  89. {
  90. raw_cmd |= FSDIO_CMD_VOLT_SWITCH;
  91. }
  92. /* 命令传输过程伴随数据传输 */
  93. if (FSDIO_CMD_FLAG_EXP_DATA & cmd_flag)
  94. {
  95. raw_cmd |= FSDIO_CMD_DAT_EXP;
  96. if (FSDIO_CMD_FLAG_WRITE_DATA & cmd_flag) /* 写卡 */
  97. {
  98. raw_cmd |= FSDIO_CMD_DAT_WRITE;
  99. }
  100. }
  101. /* 命令需要进行CRC校验 */
  102. if (FSDIO_CMD_FLAG_NEED_RESP_CRC & cmd_flag)
  103. {
  104. raw_cmd |= FSDIO_CMD_RESP_CRC;
  105. }
  106. /* 命令需要响应回复 */
  107. if (FSDIO_CMD_FLAG_EXP_RESP & cmd_flag)
  108. {
  109. raw_cmd |= FSDIO_CMD_RESP_EXP;
  110. if (FSDIO_CMD_FLAG_EXP_LONG_RESP & cmd_flag) /* 命令需要136字节长回复 */
  111. {
  112. raw_cmd |= FSDIO_CMD_RESP_LONG;
  113. }
  114. }
  115. raw_cmd |= FSDIO_CMD_INDX_SET(cmd_data_p->cmdidx);
  116. FSDIO_DEBUG("============[CMD-%d]@0x%x begin ============", cmd_data_p->cmdidx, base_addr);
  117. FSDIO_DEBUG(" cmd: 0x%x", raw_cmd);
  118. FSDIO_DEBUG(" arg: 0x%x", cmd_data_p->cmdarg);
  119. /* enable related interrupt */
  120. FSdioSetInterruptMask(instance_p, FSDIO_GENERAL_INTR,
  121. FSDIO_INTS_CMD_MASK, TRUE);
  122. FSdioSendPrivateCmd(base_addr, raw_cmd, cmd_data_p->cmdarg);
  123. FSDIO_INFO("cmd send done ...");
  124. return ret;
  125. }
  126. /**
  127. * @name: FSdioGetCmdResponse
  128. * @msg: Get cmd response and received data after wait poll status or interrupt signal
  129. * @return {FError} FSDIO_SUCCESS if get success
  130. * @param {FSdio} *instance_p, SDIO controller instance
  131. * @param {FSdioCmdData} *cmd_data_p, contents of transfer command and data
  132. */
  133. FError FSdioGetCmdResponse(FSdio *const instance_p, FSdioCmdData *const cmd_data_p)
  134. {
  135. FASSERT(instance_p);
  136. FASSERT(cmd_data_p);
  137. FError ret = FSDIO_SUCCESS;
  138. u32 reg_val;
  139. const boolean read = cmd_data_p->flag & FSDIO_CMD_FLAG_READ_DATA;
  140. uintptr base_addr = instance_p->config.base_addr;
  141. if (FT_COMPONENT_IS_READY != instance_p->is_ready)
  142. {
  143. FSDIO_ERROR("device is not yet initialized!!!");
  144. return FSDIO_ERR_NOT_INIT;
  145. }
  146. if ((NULL != cmd_data_p->data_p) && (read))
  147. {
  148. if (FSDIO_PIO_TRANS_MODE == instance_p->config.trans_mode)
  149. {
  150. ret = FSdioPIOReadData(instance_p, cmd_data_p->data_p);
  151. }
  152. }
  153. /* check response of cmd */
  154. if (FSDIO_CMD_FLAG_EXP_RESP & cmd_data_p->flag)
  155. {
  156. if (FSDIO_CMD_FLAG_EXP_LONG_RESP & cmd_data_p->flag)
  157. {
  158. cmd_data_p->response[0] = FSDIO_READ_REG(base_addr, FSDIO_RESP0_OFFSET);
  159. cmd_data_p->response[1] = FSDIO_READ_REG(base_addr, FSDIO_RESP1_OFFSET);
  160. cmd_data_p->response[2] = FSDIO_READ_REG(base_addr, FSDIO_RESP2_OFFSET);
  161. cmd_data_p->response[3] = FSDIO_READ_REG(base_addr, FSDIO_RESP3_OFFSET);
  162. FSDIO_DEBUG(" resp: 0x%x-0x%x-0x%x-0x%x",
  163. cmd_data_p->response[0], cmd_data_p->response[1],
  164. cmd_data_p->response[2], cmd_data_p->response[3]);
  165. }
  166. else
  167. {
  168. cmd_data_p->response[0] = FSDIO_READ_REG(base_addr, FSDIO_RESP0_OFFSET);
  169. FSDIO_DEBUG(" resp: 0x%x", cmd_data_p->response[0]);
  170. }
  171. }
  172. cmd_data_p->success = TRUE; /* cmd / data transfer finished successful */
  173. FSDIO_DEBUG("============[CMD-%d]@0x%x end ============", cmd_data_p->cmdidx, base_addr);
  174. /* disable related interrupt */
  175. FSdioSetInterruptMask(instance_p, FSDIO_GENERAL_INTR, FSDIO_INTS_CMD_MASK | FSDIO_INTS_DATA_MASK, FALSE);
  176. FSdioSetInterruptMask(instance_p, FSDIO_IDMA_INTR, FSDIO_DMAC_INTS_MASK, FALSE);
  177. return ret;
  178. }