| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- /*
- * Copyright : (C) 2022 Phytium Information Technology, Inc.
- * All Rights Reserved.
- *
- * This program is OPEN SOURCE software: you can redistribute it and/or modify it
- * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
- * either version 1.0 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the Phytium Public License for more details.
- *
- *
- * FilePath: fxhci_cmd.c
- * Date: 2022-02-11 13:33:12
- * LastEditTime: 2022-02-18 09:11:23
- * Description: This files is for implementation of XHCI command
- *
- * Modify History:
- * Ver Who Date Changes
- * ----- ------ -------- --------------------------------------
- * 1.0 Zhugengyu 2022/2/7 init commit
- */
- #include "fdebug.h"
- #include "fxhci_private.h"
- #define FUSB_DEBUG_TAG "FXHCI_CMD"
- #define FUSB_ERROR(format, ...) FT_DEBUG_PRINT_E(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
- #define FUSB_WARN(format, ...) FT_DEBUG_PRINT_W(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
- #define FUSB_INFO(format, ...) FT_DEBUG_PRINT_I(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
- #define FUSB_DEBUG(format, ...) FT_DEBUG_PRINT_D(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
- FXhciTrb *FXhciNextCmdTrb(FXhci *const xhci)
- {
- FXhciClearTrb(xhci->cr.cur, xhci->cr.pcs);
- return xhci->cr.cur;
- }
- void FXhciPostCmd(FXhci *const xhci)
- {
- FUSB_INFO("Command %d (@%p) ", FXHCI_TRB_GET(TT, xhci->cr.cur), xhci->cr.cur);
- FXHCI_TRB_SET(C, xhci->cr.cur, xhci->cr.pcs); /* Cycle Bit */
- ++xhci->cr.cur;
- /* pass command trb to hardware */
- WMB();
- /* Ring the doorbell */
- FXhciWriteDb32(&xhci->mmio, FXHCI_REG_DB_HOST_CONTROLLER, FXHCI_REG_DB_TARGET_HC_COMMAND);
- while (FXHCI_TRB_GET(TT, xhci->cr.cur) == FXHCI_TRB_LINK)
- {
- FUSB_DEBUG("Handling LINK pointer (@%p) ", xhci->cr.cur);
- const int tc = FXHCI_TRB_GET(TC, xhci->cr.cur); /* Completion Code */
- FXHCI_TRB_SET(C, xhci->cr.cur, xhci->cr.pcs); /* Cycle Bit */
- xhci->cr.cur = (void *)(uintptr)(xhci->cr.cur->ptr_low);
- if (tc)
- xhci->cr.pcs ^= 1;
- }
- }
- static FXhciTransCode FXhciWaitForCmd(FXhci *const xhci,
- const FXhciTrb *const cmd_trb,
- const int clear_event)
- {
- FXhciTransCode cc;
- u64 reg_val64;
- cc = FXhciWaitForCmdDone(xhci, cmd_trb, clear_event);
- if (cc != FXHCI_CC_TIMEOUT)
- return cc;
- /* Abort command on timeout */
- FUSB_ERROR("Aborting command (@%p), CRCR: 0x%x ", cmd_trb, FXhciReadOper64(&xhci->mmio, FXHCI_REG_OP_CRCR));
- /*
- * Ref. xHCI Specification Revision 1.2, May 2019.
- * Section 5.4.5, Table 5-24.
- *
- * Abort the command and stop the ring.
- */
- reg_val64 = FXhciReadOper64(&xhci->mmio, FXHCI_REG_OP_CRCR);
- reg_val64 |= FXHCI_REG_OP_CRCR_CA;
- FXhciWriteOper64(&xhci->mmio, FXHCI_REG_OP_CRCR, reg_val64);
- cc = FXhciWaitForCmdAborted(xhci, cmd_trb);
- if ((FXhciReadOper64(&xhci->mmio, FXHCI_REG_OP_CRCR) & FXHCI_REG_OP_CRCR_CRR))
- FUSB_ERROR("xhci_wait_for_command: Command ring still running");
- return cc;
- }
- FXhciTransCode FXhciCmdNop(FXhci *const xhci)
- {
- FXhciTrb *const cmd = FXhciNextCmdTrb(xhci);
- FXHCI_TRB_SET(TT, cmd, FXHCI_TRB_CMD_NOOP); /* TRB Type */
- FXhciPostCmd(xhci);
- /* wait for result in event ring */
- FXhciTransCode cc = FXhciWaitForCmdDone(xhci, cmd, 1);
- FUSB_INFO("Command ring is %srunning: cc: %d",
- (FXhciReadOper64(&xhci->mmio, FXHCI_REG_OP_CRCR) & FXHCI_REG_OP_CRCR_CRR) ? "" : "not ", /* check if cmd ring is running */
- cc);
- if (cc != FXHCI_CC_SUCCESS)
- FUSB_ERROR("noop command failed. ");
- return cc;
- }
- /*
- * xhci_cmd_* return >= 0: xhci completion code (cc)
- * < 0: driver error code
- */
- FXhciTransCode FXhciCmdEnableSlot(FXhci *const xhci, int *const slot_id)
- {
- FXhciTrb *const cmd = FXhciNextCmdTrb(xhci);
- FXHCI_TRB_SET(TT, cmd, FXHCI_TRB_CMD_ENABLE_SLOT); /* TRB Type */
- FXhciPostCmd(xhci);
- FXhciTransCode cc = FXhciWaitForCmd(xhci, cmd, 0);
- if (cc >= 0)
- {
- if (cc == FXHCI_CC_SUCCESS)
- {
- *slot_id = FXHCI_TRB_GET(ID, xhci->er.cur);
- if (*slot_id > xhci->max_slots_en)
- cc = FXHCI_CC_CONTROLLER_ERROR;
- }
- FXhciAdvanceEvtRing(xhci);
- FXhciHandleEvts(xhci);
- }
- return cc;
- }
- FXhciTransCode FXhciCmdDisableSlot(FXhci *const xhci, const int slot_id)
- {
- FXhciTrb *const cmd = FXhciNextCmdTrb(xhci);
- FXHCI_TRB_SET(TT, cmd, FXHCI_TRB_CMD_DISABLE_SLOT); /* TRB Type */
- FXHCI_TRB_SET(ID, cmd, slot_id); /* Slot ID */
- FXhciPostCmd(xhci);
- return FXhciWaitForCmd(xhci, cmd, 1);
- }
- FXhciTransCode FXhciCmdAddressDevice(FXhci *const xhci,
- const int slot_id,
- FXhciInputCtx *const ic)
- {
- FXhciTrb *const cmd = FXhciNextCmdTrb(xhci);
- FXHCI_TRB_SET(TT, cmd, FXHCI_TRB_CMD_ADDRESS_DEV); /* TRB Type */
- FXHCI_TRB_SET(ID, cmd, slot_id); /* Slot ID */
- cmd->ptr_low = (uintptr)(ic->raw);
- FXhciPostCmd(xhci);
- return FXhciWaitForCmd(xhci, cmd, 1);
- }
- FXhciTransCode FXhciCmdConfigureEp(FXhci *const xhci,
- const int slot_id,
- const int config_id,
- FXhciInputCtx *const ic)
- {
- FXhciTrb *const cmd = FXhciNextCmdTrb(xhci);
- FXHCI_TRB_SET(TT, cmd, FXHCI_TRB_CMD_CONFIGURE_EP); /* TRB Type */
- FXHCI_TRB_SET(ID, cmd, slot_id); /* Slot ID */
- cmd->ptr_low = (uintptr)(ic->raw);
- if (config_id == 0)
- FXHCI_TRB_SET(DC, cmd, 1); /* Deconfigure */
- FXhciPostCmd(xhci);
- return FXhciWaitForCmd(xhci, cmd, 1);
- }
- FXhciTransCode FXhciCmdEvaluateCtx(FXhci *const xhci,
- const int slot_id,
- FXhciInputCtx *const ic)
- {
- FXhciTrb *const cmd = FXhciNextCmdTrb(xhci);
- FXHCI_TRB_SET(TT, cmd, FXHCI_TRB_CMD_EVAL_CTX); /* TRB Type */
- FXHCI_TRB_SET(ID, cmd, slot_id); /* Slot ID */
- cmd->ptr_low = (uintptr)(ic->raw);
- FXhciPostCmd(xhci);
- return FXhciWaitForCmd(xhci, cmd, 1);
- }
- FXhciTransCode FXhciCmdResetEp(FXhci *const xhci, const int slot_id, const int ep)
- {
- FXhciTrb *const cmd = FXhciNextCmdTrb(xhci);
- FXHCI_TRB_SET(TT, cmd, FXHCI_TRB_CMD_RESET_EP); /* TRB Type */
- FXHCI_TRB_SET(ID, cmd, slot_id); /* Slot ID */
- FXHCI_TRB_SET(EP, cmd, ep); /* Endpoint ID */
- FXhciPostCmd(xhci);
- return FXhciWaitForCmd(xhci, cmd, 1);
- }
- FXhciTransCode FXhciCmdStopEp(FXhci *const xhci, const int slot_id, const int ep)
- {
- FXhciTrb *const cmd = FXhciNextCmdTrb(xhci);
- FXHCI_TRB_SET(TT, cmd, FXHCI_TRB_CMD_STOP_EP); /* TRB Type */
- FXHCI_TRB_SET(ID, cmd, slot_id); /* Slot ID */
- FXHCI_TRB_SET(EP, cmd, ep); /* Endpoint ID */
- FXhciPostCmd(xhci);
- return FXhciWaitForCmd(xhci, cmd, 1);
- }
- FXhciTransCode FXhciCmdSetTrDq(FXhci *const xhci, const int slot_id, const int ep,
- FXhciTrb *const dq_trb, const int dcs)
- {
- FXhciTrb *const cmd = FXhciNextCmdTrb(xhci);
- FXHCI_TRB_SET(TT, cmd, FXHCI_TRB_CMD_SET_TR_DQ); /* TRB Type */
- FXHCI_TRB_SET(ID, cmd, slot_id); /* Slot ID */
- FXHCI_TRB_SET(EP, cmd, ep); /* Endpoint ID */
- cmd->ptr_low = (uintptr)(dq_trb) | dcs;
- FXhciPostCmd(xhci);
- return FXhciWaitForCmd(xhci, cmd, 1);
- }
|