fxhci_cmd.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  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: fxhci_cmd.c
  15. * Date: 2022-02-11 13:33:12
  16. * LastEditTime: 2022-02-18 09:11:23
  17. * Description:  This files is for implementation of XHCI command
  18. *
  19. * Modify History:
  20. * Ver   Who        Date         Changes
  21. * ----- ------     --------    --------------------------------------
  22. * 1.0 Zhugengyu 2022/2/7 init commit
  23. */
  24. #include "fdebug.h"
  25. #include "fxhci_private.h"
  26. #define FUSB_DEBUG_TAG "FXHCI_CMD"
  27. #define FUSB_ERROR(format, ...) FT_DEBUG_PRINT_E(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
  28. #define FUSB_WARN(format, ...) FT_DEBUG_PRINT_W(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
  29. #define FUSB_INFO(format, ...) FT_DEBUG_PRINT_I(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
  30. #define FUSB_DEBUG(format, ...) FT_DEBUG_PRINT_D(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
  31. FXhciTrb *FXhciNextCmdTrb(FXhci *const xhci)
  32. {
  33. FXhciClearTrb(xhci->cr.cur, xhci->cr.pcs);
  34. return xhci->cr.cur;
  35. }
  36. void FXhciPostCmd(FXhci *const xhci)
  37. {
  38. FUSB_INFO("Command %d (@%p) ", FXHCI_TRB_GET(TT, xhci->cr.cur), xhci->cr.cur);
  39. FXHCI_TRB_SET(C, xhci->cr.cur, xhci->cr.pcs); /* Cycle Bit */
  40. ++xhci->cr.cur;
  41. /* pass command trb to hardware */
  42. WMB();
  43. /* Ring the doorbell */
  44. FXhciWriteDb32(&xhci->mmio, FXHCI_REG_DB_HOST_CONTROLLER, FXHCI_REG_DB_TARGET_HC_COMMAND);
  45. while (FXHCI_TRB_GET(TT, xhci->cr.cur) == FXHCI_TRB_LINK)
  46. {
  47. FUSB_DEBUG("Handling LINK pointer (@%p) ", xhci->cr.cur);
  48. const int tc = FXHCI_TRB_GET(TC, xhci->cr.cur); /* Completion Code */
  49. FXHCI_TRB_SET(C, xhci->cr.cur, xhci->cr.pcs); /* Cycle Bit */
  50. xhci->cr.cur = (void *)(uintptr)(xhci->cr.cur->ptr_low);
  51. if (tc)
  52. xhci->cr.pcs ^= 1;
  53. }
  54. }
  55. static FXhciTransCode FXhciWaitForCmd(FXhci *const xhci,
  56. const FXhciTrb *const cmd_trb,
  57. const int clear_event)
  58. {
  59. FXhciTransCode cc;
  60. u64 reg_val64;
  61. cc = FXhciWaitForCmdDone(xhci, cmd_trb, clear_event);
  62. if (cc != FXHCI_CC_TIMEOUT)
  63. return cc;
  64. /* Abort command on timeout */
  65. FUSB_ERROR("Aborting command (@%p), CRCR: 0x%x ", cmd_trb, FXhciReadOper64(&xhci->mmio, FXHCI_REG_OP_CRCR));
  66. /*
  67. * Ref. xHCI Specification Revision 1.2, May 2019.
  68. * Section 5.4.5, Table 5-24.
  69. *
  70. * Abort the command and stop the ring.
  71. */
  72. reg_val64 = FXhciReadOper64(&xhci->mmio, FXHCI_REG_OP_CRCR);
  73. reg_val64 |= FXHCI_REG_OP_CRCR_CA;
  74. FXhciWriteOper64(&xhci->mmio, FXHCI_REG_OP_CRCR, reg_val64);
  75. cc = FXhciWaitForCmdAborted(xhci, cmd_trb);
  76. if ((FXhciReadOper64(&xhci->mmio, FXHCI_REG_OP_CRCR) & FXHCI_REG_OP_CRCR_CRR))
  77. FUSB_ERROR("xhci_wait_for_command: Command ring still running");
  78. return cc;
  79. }
  80. FXhciTransCode FXhciCmdNop(FXhci *const xhci)
  81. {
  82. FXhciTrb *const cmd = FXhciNextCmdTrb(xhci);
  83. FXHCI_TRB_SET(TT, cmd, FXHCI_TRB_CMD_NOOP); /* TRB Type */
  84. FXhciPostCmd(xhci);
  85. /* wait for result in event ring */
  86. FXhciTransCode cc = FXhciWaitForCmdDone(xhci, cmd, 1);
  87. FUSB_INFO("Command ring is %srunning: cc: %d",
  88. (FXhciReadOper64(&xhci->mmio, FXHCI_REG_OP_CRCR) & FXHCI_REG_OP_CRCR_CRR) ? "" : "not ", /* check if cmd ring is running */
  89. cc);
  90. if (cc != FXHCI_CC_SUCCESS)
  91. FUSB_ERROR("noop command failed. ");
  92. return cc;
  93. }
  94. /*
  95. * xhci_cmd_* return >= 0: xhci completion code (cc)
  96. * < 0: driver error code
  97. */
  98. FXhciTransCode FXhciCmdEnableSlot(FXhci *const xhci, int *const slot_id)
  99. {
  100. FXhciTrb *const cmd = FXhciNextCmdTrb(xhci);
  101. FXHCI_TRB_SET(TT, cmd, FXHCI_TRB_CMD_ENABLE_SLOT); /* TRB Type */
  102. FXhciPostCmd(xhci);
  103. FXhciTransCode cc = FXhciWaitForCmd(xhci, cmd, 0);
  104. if (cc >= 0)
  105. {
  106. if (cc == FXHCI_CC_SUCCESS)
  107. {
  108. *slot_id = FXHCI_TRB_GET(ID, xhci->er.cur);
  109. if (*slot_id > xhci->max_slots_en)
  110. cc = FXHCI_CC_CONTROLLER_ERROR;
  111. }
  112. FXhciAdvanceEvtRing(xhci);
  113. FXhciHandleEvts(xhci);
  114. }
  115. return cc;
  116. }
  117. FXhciTransCode FXhciCmdDisableSlot(FXhci *const xhci, const int slot_id)
  118. {
  119. FXhciTrb *const cmd = FXhciNextCmdTrb(xhci);
  120. FXHCI_TRB_SET(TT, cmd, FXHCI_TRB_CMD_DISABLE_SLOT); /* TRB Type */
  121. FXHCI_TRB_SET(ID, cmd, slot_id); /* Slot ID */
  122. FXhciPostCmd(xhci);
  123. return FXhciWaitForCmd(xhci, cmd, 1);
  124. }
  125. FXhciTransCode FXhciCmdAddressDevice(FXhci *const xhci,
  126. const int slot_id,
  127. FXhciInputCtx *const ic)
  128. {
  129. FXhciTrb *const cmd = FXhciNextCmdTrb(xhci);
  130. FXHCI_TRB_SET(TT, cmd, FXHCI_TRB_CMD_ADDRESS_DEV); /* TRB Type */
  131. FXHCI_TRB_SET(ID, cmd, slot_id); /* Slot ID */
  132. cmd->ptr_low = (uintptr)(ic->raw);
  133. FXhciPostCmd(xhci);
  134. return FXhciWaitForCmd(xhci, cmd, 1);
  135. }
  136. FXhciTransCode FXhciCmdConfigureEp(FXhci *const xhci,
  137. const int slot_id,
  138. const int config_id,
  139. FXhciInputCtx *const ic)
  140. {
  141. FXhciTrb *const cmd = FXhciNextCmdTrb(xhci);
  142. FXHCI_TRB_SET(TT, cmd, FXHCI_TRB_CMD_CONFIGURE_EP); /* TRB Type */
  143. FXHCI_TRB_SET(ID, cmd, slot_id); /* Slot ID */
  144. cmd->ptr_low = (uintptr)(ic->raw);
  145. if (config_id == 0)
  146. FXHCI_TRB_SET(DC, cmd, 1); /* Deconfigure */
  147. FXhciPostCmd(xhci);
  148. return FXhciWaitForCmd(xhci, cmd, 1);
  149. }
  150. FXhciTransCode FXhciCmdEvaluateCtx(FXhci *const xhci,
  151. const int slot_id,
  152. FXhciInputCtx *const ic)
  153. {
  154. FXhciTrb *const cmd = FXhciNextCmdTrb(xhci);
  155. FXHCI_TRB_SET(TT, cmd, FXHCI_TRB_CMD_EVAL_CTX); /* TRB Type */
  156. FXHCI_TRB_SET(ID, cmd, slot_id); /* Slot ID */
  157. cmd->ptr_low = (uintptr)(ic->raw);
  158. FXhciPostCmd(xhci);
  159. return FXhciWaitForCmd(xhci, cmd, 1);
  160. }
  161. FXhciTransCode FXhciCmdResetEp(FXhci *const xhci, const int slot_id, const int ep)
  162. {
  163. FXhciTrb *const cmd = FXhciNextCmdTrb(xhci);
  164. FXHCI_TRB_SET(TT, cmd, FXHCI_TRB_CMD_RESET_EP); /* TRB Type */
  165. FXHCI_TRB_SET(ID, cmd, slot_id); /* Slot ID */
  166. FXHCI_TRB_SET(EP, cmd, ep); /* Endpoint ID */
  167. FXhciPostCmd(xhci);
  168. return FXhciWaitForCmd(xhci, cmd, 1);
  169. }
  170. FXhciTransCode FXhciCmdStopEp(FXhci *const xhci, const int slot_id, const int ep)
  171. {
  172. FXhciTrb *const cmd = FXhciNextCmdTrb(xhci);
  173. FXHCI_TRB_SET(TT, cmd, FXHCI_TRB_CMD_STOP_EP); /* TRB Type */
  174. FXHCI_TRB_SET(ID, cmd, slot_id); /* Slot ID */
  175. FXHCI_TRB_SET(EP, cmd, ep); /* Endpoint ID */
  176. FXhciPostCmd(xhci);
  177. return FXhciWaitForCmd(xhci, cmd, 1);
  178. }
  179. FXhciTransCode FXhciCmdSetTrDq(FXhci *const xhci, const int slot_id, const int ep,
  180. FXhciTrb *const dq_trb, const int dcs)
  181. {
  182. FXhciTrb *const cmd = FXhciNextCmdTrb(xhci);
  183. FXHCI_TRB_SET(TT, cmd, FXHCI_TRB_CMD_SET_TR_DQ); /* TRB Type */
  184. FXHCI_TRB_SET(ID, cmd, slot_id); /* Slot ID */
  185. FXHCI_TRB_SET(EP, cmd, ep); /* Endpoint ID */
  186. cmd->ptr_low = (uintptr)(dq_trb) | dcs;
  187. FXhciPostCmd(xhci);
  188. return FXhciWaitForCmd(xhci, cmd, 1);
  189. }