162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * gadget.c - DesignWare USB3 DRD Controller Gadget Framework Link 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2010-2011 Texas Instruments Incorporated - https://www.ti.com 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Authors: Felipe Balbi <balbi@ti.com>, 862306a36Sopenharmony_ci * Sebastian Andrzej Siewior <bigeasy@linutronix.de> 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/kernel.h> 1262306a36Sopenharmony_ci#include <linux/delay.h> 1362306a36Sopenharmony_ci#include <linux/slab.h> 1462306a36Sopenharmony_ci#include <linux/spinlock.h> 1562306a36Sopenharmony_ci#include <linux/platform_device.h> 1662306a36Sopenharmony_ci#include <linux/pm_runtime.h> 1762306a36Sopenharmony_ci#include <linux/interrupt.h> 1862306a36Sopenharmony_ci#include <linux/io.h> 1962306a36Sopenharmony_ci#include <linux/list.h> 2062306a36Sopenharmony_ci#include <linux/dma-mapping.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#include <linux/usb/ch9.h> 2362306a36Sopenharmony_ci#include <linux/usb/gadget.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#include "debug.h" 2662306a36Sopenharmony_ci#include "core.h" 2762306a36Sopenharmony_ci#include "gadget.h" 2862306a36Sopenharmony_ci#include "io.h" 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#define DWC3_ALIGN_FRAME(d, n) (((d)->frame_number + ((d)->interval * (n))) \ 3162306a36Sopenharmony_ci & ~((d)->interval - 1)) 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci/** 3462306a36Sopenharmony_ci * dwc3_gadget_set_test_mode - enables usb2 test modes 3562306a36Sopenharmony_ci * @dwc: pointer to our context structure 3662306a36Sopenharmony_ci * @mode: the mode to set (J, K SE0 NAK, Force Enable) 3762306a36Sopenharmony_ci * 3862306a36Sopenharmony_ci * Caller should take care of locking. This function will return 0 on 3962306a36Sopenharmony_ci * success or -EINVAL if wrong Test Selector is passed. 4062306a36Sopenharmony_ci */ 4162306a36Sopenharmony_ciint dwc3_gadget_set_test_mode(struct dwc3 *dwc, int mode) 4262306a36Sopenharmony_ci{ 4362306a36Sopenharmony_ci u32 reg; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_DCTL); 4662306a36Sopenharmony_ci reg &= ~DWC3_DCTL_TSTCTRL_MASK; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci switch (mode) { 4962306a36Sopenharmony_ci case USB_TEST_J: 5062306a36Sopenharmony_ci case USB_TEST_K: 5162306a36Sopenharmony_ci case USB_TEST_SE0_NAK: 5262306a36Sopenharmony_ci case USB_TEST_PACKET: 5362306a36Sopenharmony_ci case USB_TEST_FORCE_ENABLE: 5462306a36Sopenharmony_ci reg |= mode << 1; 5562306a36Sopenharmony_ci break; 5662306a36Sopenharmony_ci default: 5762306a36Sopenharmony_ci return -EINVAL; 5862306a36Sopenharmony_ci } 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci dwc3_gadget_dctl_write_safe(dwc, reg); 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci return 0; 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci/** 6662306a36Sopenharmony_ci * dwc3_gadget_get_link_state - gets current state of usb link 6762306a36Sopenharmony_ci * @dwc: pointer to our context structure 6862306a36Sopenharmony_ci * 6962306a36Sopenharmony_ci * Caller should take care of locking. This function will 7062306a36Sopenharmony_ci * return the link state on success (>= 0) or -ETIMEDOUT. 7162306a36Sopenharmony_ci */ 7262306a36Sopenharmony_ciint dwc3_gadget_get_link_state(struct dwc3 *dwc) 7362306a36Sopenharmony_ci{ 7462306a36Sopenharmony_ci u32 reg; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_DSTS); 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci return DWC3_DSTS_USBLNKST(reg); 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci/** 8262306a36Sopenharmony_ci * dwc3_gadget_set_link_state - sets usb link to a particular state 8362306a36Sopenharmony_ci * @dwc: pointer to our context structure 8462306a36Sopenharmony_ci * @state: the state to put link into 8562306a36Sopenharmony_ci * 8662306a36Sopenharmony_ci * Caller should take care of locking. This function will 8762306a36Sopenharmony_ci * return 0 on success or -ETIMEDOUT. 8862306a36Sopenharmony_ci */ 8962306a36Sopenharmony_ciint dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci int retries = 10000; 9262306a36Sopenharmony_ci u32 reg; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci /* 9562306a36Sopenharmony_ci * Wait until device controller is ready. Only applies to 1.94a and 9662306a36Sopenharmony_ci * later RTL. 9762306a36Sopenharmony_ci */ 9862306a36Sopenharmony_ci if (!DWC3_VER_IS_PRIOR(DWC3, 194A)) { 9962306a36Sopenharmony_ci while (--retries) { 10062306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_DSTS); 10162306a36Sopenharmony_ci if (reg & DWC3_DSTS_DCNRD) 10262306a36Sopenharmony_ci udelay(5); 10362306a36Sopenharmony_ci else 10462306a36Sopenharmony_ci break; 10562306a36Sopenharmony_ci } 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci if (retries <= 0) 10862306a36Sopenharmony_ci return -ETIMEDOUT; 10962306a36Sopenharmony_ci } 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_DCTL); 11262306a36Sopenharmony_ci reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci /* set no action before sending new link state change */ 11562306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_DCTL, reg); 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci /* set requested state */ 11862306a36Sopenharmony_ci reg |= DWC3_DCTL_ULSTCHNGREQ(state); 11962306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_DCTL, reg); 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci /* 12262306a36Sopenharmony_ci * The following code is racy when called from dwc3_gadget_wakeup, 12362306a36Sopenharmony_ci * and is not needed, at least on newer versions 12462306a36Sopenharmony_ci */ 12562306a36Sopenharmony_ci if (!DWC3_VER_IS_PRIOR(DWC3, 194A)) 12662306a36Sopenharmony_ci return 0; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci /* wait for a change in DSTS */ 12962306a36Sopenharmony_ci retries = 10000; 13062306a36Sopenharmony_ci while (--retries) { 13162306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_DSTS); 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci if (DWC3_DSTS_USBLNKST(reg) == state) 13462306a36Sopenharmony_ci return 0; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci udelay(5); 13762306a36Sopenharmony_ci } 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci return -ETIMEDOUT; 14062306a36Sopenharmony_ci} 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_cistatic void dwc3_ep0_reset_state(struct dwc3 *dwc) 14362306a36Sopenharmony_ci{ 14462306a36Sopenharmony_ci unsigned int dir; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci if (dwc->ep0state != EP0_SETUP_PHASE) { 14762306a36Sopenharmony_ci dir = !!dwc->ep0_expect_in; 14862306a36Sopenharmony_ci if (dwc->ep0state == EP0_DATA_PHASE) 14962306a36Sopenharmony_ci dwc3_ep0_end_control_data(dwc, dwc->eps[dir]); 15062306a36Sopenharmony_ci else 15162306a36Sopenharmony_ci dwc3_ep0_end_control_data(dwc, dwc->eps[!dir]); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci dwc->eps[0]->trb_enqueue = 0; 15462306a36Sopenharmony_ci dwc->eps[1]->trb_enqueue = 0; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci dwc3_ep0_stall_and_restart(dwc); 15762306a36Sopenharmony_ci } 15862306a36Sopenharmony_ci} 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci/** 16162306a36Sopenharmony_ci * dwc3_ep_inc_trb - increment a trb index. 16262306a36Sopenharmony_ci * @index: Pointer to the TRB index to increment. 16362306a36Sopenharmony_ci * 16462306a36Sopenharmony_ci * The index should never point to the link TRB. After incrementing, 16562306a36Sopenharmony_ci * if it is point to the link TRB, wrap around to the beginning. The 16662306a36Sopenharmony_ci * link TRB is always at the last TRB entry. 16762306a36Sopenharmony_ci */ 16862306a36Sopenharmony_cistatic void dwc3_ep_inc_trb(u8 *index) 16962306a36Sopenharmony_ci{ 17062306a36Sopenharmony_ci (*index)++; 17162306a36Sopenharmony_ci if (*index == (DWC3_TRB_NUM - 1)) 17262306a36Sopenharmony_ci *index = 0; 17362306a36Sopenharmony_ci} 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci/** 17662306a36Sopenharmony_ci * dwc3_ep_inc_enq - increment endpoint's enqueue pointer 17762306a36Sopenharmony_ci * @dep: The endpoint whose enqueue pointer we're incrementing 17862306a36Sopenharmony_ci */ 17962306a36Sopenharmony_cistatic void dwc3_ep_inc_enq(struct dwc3_ep *dep) 18062306a36Sopenharmony_ci{ 18162306a36Sopenharmony_ci dwc3_ep_inc_trb(&dep->trb_enqueue); 18262306a36Sopenharmony_ci} 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci/** 18562306a36Sopenharmony_ci * dwc3_ep_inc_deq - increment endpoint's dequeue pointer 18662306a36Sopenharmony_ci * @dep: The endpoint whose enqueue pointer we're incrementing 18762306a36Sopenharmony_ci */ 18862306a36Sopenharmony_cistatic void dwc3_ep_inc_deq(struct dwc3_ep *dep) 18962306a36Sopenharmony_ci{ 19062306a36Sopenharmony_ci dwc3_ep_inc_trb(&dep->trb_dequeue); 19162306a36Sopenharmony_ci} 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_cistatic void dwc3_gadget_del_and_unmap_request(struct dwc3_ep *dep, 19462306a36Sopenharmony_ci struct dwc3_request *req, int status) 19562306a36Sopenharmony_ci{ 19662306a36Sopenharmony_ci struct dwc3 *dwc = dep->dwc; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci list_del(&req->list); 19962306a36Sopenharmony_ci req->remaining = 0; 20062306a36Sopenharmony_ci req->needs_extra_trb = false; 20162306a36Sopenharmony_ci req->num_trbs = 0; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci if (req->request.status == -EINPROGRESS) 20462306a36Sopenharmony_ci req->request.status = status; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci if (req->trb) 20762306a36Sopenharmony_ci usb_gadget_unmap_request_by_dev(dwc->sysdev, 20862306a36Sopenharmony_ci &req->request, req->direction); 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci req->trb = NULL; 21162306a36Sopenharmony_ci trace_dwc3_gadget_giveback(req); 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci if (dep->number > 1) 21462306a36Sopenharmony_ci pm_runtime_put(dwc->dev); 21562306a36Sopenharmony_ci} 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci/** 21862306a36Sopenharmony_ci * dwc3_gadget_giveback - call struct usb_request's ->complete callback 21962306a36Sopenharmony_ci * @dep: The endpoint to whom the request belongs to 22062306a36Sopenharmony_ci * @req: The request we're giving back 22162306a36Sopenharmony_ci * @status: completion code for the request 22262306a36Sopenharmony_ci * 22362306a36Sopenharmony_ci * Must be called with controller's lock held and interrupts disabled. This 22462306a36Sopenharmony_ci * function will unmap @req and call its ->complete() callback to notify upper 22562306a36Sopenharmony_ci * layers that it has completed. 22662306a36Sopenharmony_ci */ 22762306a36Sopenharmony_civoid dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, 22862306a36Sopenharmony_ci int status) 22962306a36Sopenharmony_ci{ 23062306a36Sopenharmony_ci struct dwc3 *dwc = dep->dwc; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci dwc3_gadget_del_and_unmap_request(dep, req, status); 23362306a36Sopenharmony_ci req->status = DWC3_REQUEST_STATUS_COMPLETED; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci spin_unlock(&dwc->lock); 23662306a36Sopenharmony_ci usb_gadget_giveback_request(&dep->endpoint, &req->request); 23762306a36Sopenharmony_ci spin_lock(&dwc->lock); 23862306a36Sopenharmony_ci} 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci/** 24162306a36Sopenharmony_ci * dwc3_send_gadget_generic_command - issue a generic command for the controller 24262306a36Sopenharmony_ci * @dwc: pointer to the controller context 24362306a36Sopenharmony_ci * @cmd: the command to be issued 24462306a36Sopenharmony_ci * @param: command parameter 24562306a36Sopenharmony_ci * 24662306a36Sopenharmony_ci * Caller should take care of locking. Issue @cmd with a given @param to @dwc 24762306a36Sopenharmony_ci * and wait for its completion. 24862306a36Sopenharmony_ci */ 24962306a36Sopenharmony_ciint dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned int cmd, 25062306a36Sopenharmony_ci u32 param) 25162306a36Sopenharmony_ci{ 25262306a36Sopenharmony_ci u32 timeout = 500; 25362306a36Sopenharmony_ci int status = 0; 25462306a36Sopenharmony_ci int ret = 0; 25562306a36Sopenharmony_ci u32 reg; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_DGCMDPAR, param); 25862306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_DGCMD, cmd | DWC3_DGCMD_CMDACT); 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci do { 26162306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_DGCMD); 26262306a36Sopenharmony_ci if (!(reg & DWC3_DGCMD_CMDACT)) { 26362306a36Sopenharmony_ci status = DWC3_DGCMD_STATUS(reg); 26462306a36Sopenharmony_ci if (status) 26562306a36Sopenharmony_ci ret = -EINVAL; 26662306a36Sopenharmony_ci break; 26762306a36Sopenharmony_ci } 26862306a36Sopenharmony_ci } while (--timeout); 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci if (!timeout) { 27162306a36Sopenharmony_ci ret = -ETIMEDOUT; 27262306a36Sopenharmony_ci status = -ETIMEDOUT; 27362306a36Sopenharmony_ci } 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci trace_dwc3_gadget_generic_cmd(cmd, param, status); 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci return ret; 27862306a36Sopenharmony_ci} 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_cistatic int __dwc3_gadget_wakeup(struct dwc3 *dwc, bool async); 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci/** 28362306a36Sopenharmony_ci * dwc3_send_gadget_ep_cmd - issue an endpoint command 28462306a36Sopenharmony_ci * @dep: the endpoint to which the command is going to be issued 28562306a36Sopenharmony_ci * @cmd: the command to be issued 28662306a36Sopenharmony_ci * @params: parameters to the command 28762306a36Sopenharmony_ci * 28862306a36Sopenharmony_ci * Caller should handle locking. This function will issue @cmd with given 28962306a36Sopenharmony_ci * @params to @dep and wait for its completion. 29062306a36Sopenharmony_ci */ 29162306a36Sopenharmony_ciint dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd, 29262306a36Sopenharmony_ci struct dwc3_gadget_ep_cmd_params *params) 29362306a36Sopenharmony_ci{ 29462306a36Sopenharmony_ci const struct usb_endpoint_descriptor *desc = dep->endpoint.desc; 29562306a36Sopenharmony_ci struct dwc3 *dwc = dep->dwc; 29662306a36Sopenharmony_ci u32 timeout = 5000; 29762306a36Sopenharmony_ci u32 saved_config = 0; 29862306a36Sopenharmony_ci u32 reg; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci int cmd_status = 0; 30162306a36Sopenharmony_ci int ret = -EINVAL; 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci /* 30462306a36Sopenharmony_ci * When operating in USB 2.0 speeds (HS/FS), if GUSB2PHYCFG.ENBLSLPM or 30562306a36Sopenharmony_ci * GUSB2PHYCFG.SUSPHY is set, it must be cleared before issuing an 30662306a36Sopenharmony_ci * endpoint command. 30762306a36Sopenharmony_ci * 30862306a36Sopenharmony_ci * Save and clear both GUSB2PHYCFG.ENBLSLPM and GUSB2PHYCFG.SUSPHY 30962306a36Sopenharmony_ci * settings. Restore them after the command is completed. 31062306a36Sopenharmony_ci * 31162306a36Sopenharmony_ci * DWC_usb3 3.30a and DWC_usb31 1.90a programming guide section 3.2.2 31262306a36Sopenharmony_ci */ 31362306a36Sopenharmony_ci if (dwc->gadget->speed <= USB_SPEED_HIGH || 31462306a36Sopenharmony_ci DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_ENDTRANSFER) { 31562306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 31662306a36Sopenharmony_ci if (unlikely(reg & DWC3_GUSB2PHYCFG_SUSPHY)) { 31762306a36Sopenharmony_ci saved_config |= DWC3_GUSB2PHYCFG_SUSPHY; 31862306a36Sopenharmony_ci reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; 31962306a36Sopenharmony_ci } 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci if (reg & DWC3_GUSB2PHYCFG_ENBLSLPM) { 32262306a36Sopenharmony_ci saved_config |= DWC3_GUSB2PHYCFG_ENBLSLPM; 32362306a36Sopenharmony_ci reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM; 32462306a36Sopenharmony_ci } 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci if (saved_config) 32762306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 32862306a36Sopenharmony_ci } 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci if (DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_STARTTRANSFER) { 33162306a36Sopenharmony_ci int link_state; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci /* 33462306a36Sopenharmony_ci * Initiate remote wakeup if the link state is in U3 when 33562306a36Sopenharmony_ci * operating in SS/SSP or L1/L2 when operating in HS/FS. If the 33662306a36Sopenharmony_ci * link state is in U1/U2, no remote wakeup is needed. The Start 33762306a36Sopenharmony_ci * Transfer command will initiate the link recovery. 33862306a36Sopenharmony_ci */ 33962306a36Sopenharmony_ci link_state = dwc3_gadget_get_link_state(dwc); 34062306a36Sopenharmony_ci switch (link_state) { 34162306a36Sopenharmony_ci case DWC3_LINK_STATE_U2: 34262306a36Sopenharmony_ci if (dwc->gadget->speed >= USB_SPEED_SUPER) 34362306a36Sopenharmony_ci break; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci fallthrough; 34662306a36Sopenharmony_ci case DWC3_LINK_STATE_U3: 34762306a36Sopenharmony_ci ret = __dwc3_gadget_wakeup(dwc, false); 34862306a36Sopenharmony_ci dev_WARN_ONCE(dwc->dev, ret, "wakeup failed --> %d\n", 34962306a36Sopenharmony_ci ret); 35062306a36Sopenharmony_ci break; 35162306a36Sopenharmony_ci } 35262306a36Sopenharmony_ci } 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci /* 35562306a36Sopenharmony_ci * For some commands such as Update Transfer command, DEPCMDPARn 35662306a36Sopenharmony_ci * registers are reserved. Since the driver often sends Update Transfer 35762306a36Sopenharmony_ci * command, don't write to DEPCMDPARn to avoid register write delays and 35862306a36Sopenharmony_ci * improve performance. 35962306a36Sopenharmony_ci */ 36062306a36Sopenharmony_ci if (DWC3_DEPCMD_CMD(cmd) != DWC3_DEPCMD_UPDATETRANSFER) { 36162306a36Sopenharmony_ci dwc3_writel(dep->regs, DWC3_DEPCMDPAR0, params->param0); 36262306a36Sopenharmony_ci dwc3_writel(dep->regs, DWC3_DEPCMDPAR1, params->param1); 36362306a36Sopenharmony_ci dwc3_writel(dep->regs, DWC3_DEPCMDPAR2, params->param2); 36462306a36Sopenharmony_ci } 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci /* 36762306a36Sopenharmony_ci * Synopsys Databook 2.60a states in section 6.3.2.5.6 of that if we're 36862306a36Sopenharmony_ci * not relying on XferNotReady, we can make use of a special "No 36962306a36Sopenharmony_ci * Response Update Transfer" command where we should clear both CmdAct 37062306a36Sopenharmony_ci * and CmdIOC bits. 37162306a36Sopenharmony_ci * 37262306a36Sopenharmony_ci * With this, we don't need to wait for command completion and can 37362306a36Sopenharmony_ci * straight away issue further commands to the endpoint. 37462306a36Sopenharmony_ci * 37562306a36Sopenharmony_ci * NOTICE: We're making an assumption that control endpoints will never 37662306a36Sopenharmony_ci * make use of Update Transfer command. This is a safe assumption 37762306a36Sopenharmony_ci * because we can never have more than one request at a time with 37862306a36Sopenharmony_ci * Control Endpoints. If anybody changes that assumption, this chunk 37962306a36Sopenharmony_ci * needs to be updated accordingly. 38062306a36Sopenharmony_ci */ 38162306a36Sopenharmony_ci if (DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_UPDATETRANSFER && 38262306a36Sopenharmony_ci !usb_endpoint_xfer_isoc(desc)) 38362306a36Sopenharmony_ci cmd &= ~(DWC3_DEPCMD_CMDIOC | DWC3_DEPCMD_CMDACT); 38462306a36Sopenharmony_ci else 38562306a36Sopenharmony_ci cmd |= DWC3_DEPCMD_CMDACT; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci dwc3_writel(dep->regs, DWC3_DEPCMD, cmd); 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci if (!(cmd & DWC3_DEPCMD_CMDACT) || 39062306a36Sopenharmony_ci (DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_ENDTRANSFER && 39162306a36Sopenharmony_ci !(cmd & DWC3_DEPCMD_CMDIOC))) { 39262306a36Sopenharmony_ci ret = 0; 39362306a36Sopenharmony_ci goto skip_status; 39462306a36Sopenharmony_ci } 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci do { 39762306a36Sopenharmony_ci reg = dwc3_readl(dep->regs, DWC3_DEPCMD); 39862306a36Sopenharmony_ci if (!(reg & DWC3_DEPCMD_CMDACT)) { 39962306a36Sopenharmony_ci cmd_status = DWC3_DEPCMD_STATUS(reg); 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci switch (cmd_status) { 40262306a36Sopenharmony_ci case 0: 40362306a36Sopenharmony_ci ret = 0; 40462306a36Sopenharmony_ci break; 40562306a36Sopenharmony_ci case DEPEVT_TRANSFER_NO_RESOURCE: 40662306a36Sopenharmony_ci dev_WARN(dwc->dev, "No resource for %s\n", 40762306a36Sopenharmony_ci dep->name); 40862306a36Sopenharmony_ci ret = -EINVAL; 40962306a36Sopenharmony_ci break; 41062306a36Sopenharmony_ci case DEPEVT_TRANSFER_BUS_EXPIRY: 41162306a36Sopenharmony_ci /* 41262306a36Sopenharmony_ci * SW issues START TRANSFER command to 41362306a36Sopenharmony_ci * isochronous ep with future frame interval. If 41462306a36Sopenharmony_ci * future interval time has already passed when 41562306a36Sopenharmony_ci * core receives the command, it will respond 41662306a36Sopenharmony_ci * with an error status of 'Bus Expiry'. 41762306a36Sopenharmony_ci * 41862306a36Sopenharmony_ci * Instead of always returning -EINVAL, let's 41962306a36Sopenharmony_ci * give a hint to the gadget driver that this is 42062306a36Sopenharmony_ci * the case by returning -EAGAIN. 42162306a36Sopenharmony_ci */ 42262306a36Sopenharmony_ci ret = -EAGAIN; 42362306a36Sopenharmony_ci break; 42462306a36Sopenharmony_ci default: 42562306a36Sopenharmony_ci dev_WARN(dwc->dev, "UNKNOWN cmd status\n"); 42662306a36Sopenharmony_ci } 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci break; 42962306a36Sopenharmony_ci } 43062306a36Sopenharmony_ci } while (--timeout); 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci if (timeout == 0) { 43362306a36Sopenharmony_ci ret = -ETIMEDOUT; 43462306a36Sopenharmony_ci cmd_status = -ETIMEDOUT; 43562306a36Sopenharmony_ci } 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ciskip_status: 43862306a36Sopenharmony_ci trace_dwc3_gadget_ep_cmd(dep, cmd, params, cmd_status); 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci if (DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_STARTTRANSFER) { 44162306a36Sopenharmony_ci if (ret == 0) 44262306a36Sopenharmony_ci dep->flags |= DWC3_EP_TRANSFER_STARTED; 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci if (ret != -ETIMEDOUT) 44562306a36Sopenharmony_ci dwc3_gadget_ep_get_transfer_index(dep); 44662306a36Sopenharmony_ci } 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci if (saved_config) { 44962306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 45062306a36Sopenharmony_ci reg |= saved_config; 45162306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 45262306a36Sopenharmony_ci } 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci return ret; 45562306a36Sopenharmony_ci} 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_cistatic int dwc3_send_clear_stall_ep_cmd(struct dwc3_ep *dep) 45862306a36Sopenharmony_ci{ 45962306a36Sopenharmony_ci struct dwc3 *dwc = dep->dwc; 46062306a36Sopenharmony_ci struct dwc3_gadget_ep_cmd_params params; 46162306a36Sopenharmony_ci u32 cmd = DWC3_DEPCMD_CLEARSTALL; 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci /* 46462306a36Sopenharmony_ci * As of core revision 2.60a the recommended programming model 46562306a36Sopenharmony_ci * is to set the ClearPendIN bit when issuing a Clear Stall EP 46662306a36Sopenharmony_ci * command for IN endpoints. This is to prevent an issue where 46762306a36Sopenharmony_ci * some (non-compliant) hosts may not send ACK TPs for pending 46862306a36Sopenharmony_ci * IN transfers due to a mishandled error condition. Synopsys 46962306a36Sopenharmony_ci * STAR 9000614252. 47062306a36Sopenharmony_ci */ 47162306a36Sopenharmony_ci if (dep->direction && 47262306a36Sopenharmony_ci !DWC3_VER_IS_PRIOR(DWC3, 260A) && 47362306a36Sopenharmony_ci (dwc->gadget->speed >= USB_SPEED_SUPER)) 47462306a36Sopenharmony_ci cmd |= DWC3_DEPCMD_CLEARPENDIN; 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci memset(¶ms, 0, sizeof(params)); 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci return dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms); 47962306a36Sopenharmony_ci} 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_cistatic dma_addr_t dwc3_trb_dma_offset(struct dwc3_ep *dep, 48262306a36Sopenharmony_ci struct dwc3_trb *trb) 48362306a36Sopenharmony_ci{ 48462306a36Sopenharmony_ci u32 offset = (char *) trb - (char *) dep->trb_pool; 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci return dep->trb_pool_dma + offset; 48762306a36Sopenharmony_ci} 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_cistatic int dwc3_alloc_trb_pool(struct dwc3_ep *dep) 49062306a36Sopenharmony_ci{ 49162306a36Sopenharmony_ci struct dwc3 *dwc = dep->dwc; 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci if (dep->trb_pool) 49462306a36Sopenharmony_ci return 0; 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci dep->trb_pool = dma_alloc_coherent(dwc->sysdev, 49762306a36Sopenharmony_ci sizeof(struct dwc3_trb) * DWC3_TRB_NUM, 49862306a36Sopenharmony_ci &dep->trb_pool_dma, GFP_KERNEL); 49962306a36Sopenharmony_ci if (!dep->trb_pool) { 50062306a36Sopenharmony_ci dev_err(dep->dwc->dev, "failed to allocate trb pool for %s\n", 50162306a36Sopenharmony_ci dep->name); 50262306a36Sopenharmony_ci return -ENOMEM; 50362306a36Sopenharmony_ci } 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci return 0; 50662306a36Sopenharmony_ci} 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_cistatic void dwc3_free_trb_pool(struct dwc3_ep *dep) 50962306a36Sopenharmony_ci{ 51062306a36Sopenharmony_ci struct dwc3 *dwc = dep->dwc; 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci dma_free_coherent(dwc->sysdev, sizeof(struct dwc3_trb) * DWC3_TRB_NUM, 51362306a36Sopenharmony_ci dep->trb_pool, dep->trb_pool_dma); 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci dep->trb_pool = NULL; 51662306a36Sopenharmony_ci dep->trb_pool_dma = 0; 51762306a36Sopenharmony_ci} 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_cistatic int dwc3_gadget_set_xfer_resource(struct dwc3_ep *dep) 52062306a36Sopenharmony_ci{ 52162306a36Sopenharmony_ci struct dwc3_gadget_ep_cmd_params params; 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci memset(¶ms, 0x00, sizeof(params)); 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci params.param0 = DWC3_DEPXFERCFG_NUM_XFER_RES(1); 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci return dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_SETTRANSFRESOURCE, 52862306a36Sopenharmony_ci ¶ms); 52962306a36Sopenharmony_ci} 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci/** 53262306a36Sopenharmony_ci * dwc3_gadget_start_config - configure ep resources 53362306a36Sopenharmony_ci * @dep: endpoint that is being enabled 53462306a36Sopenharmony_ci * 53562306a36Sopenharmony_ci * Issue a %DWC3_DEPCMD_DEPSTARTCFG command to @dep. After the command's 53662306a36Sopenharmony_ci * completion, it will set Transfer Resource for all available endpoints. 53762306a36Sopenharmony_ci * 53862306a36Sopenharmony_ci * The assignment of transfer resources cannot perfectly follow the data book 53962306a36Sopenharmony_ci * due to the fact that the controller driver does not have all knowledge of the 54062306a36Sopenharmony_ci * configuration in advance. It is given this information piecemeal by the 54162306a36Sopenharmony_ci * composite gadget framework after every SET_CONFIGURATION and 54262306a36Sopenharmony_ci * SET_INTERFACE. Trying to follow the databook programming model in this 54362306a36Sopenharmony_ci * scenario can cause errors. For two reasons: 54462306a36Sopenharmony_ci * 54562306a36Sopenharmony_ci * 1) The databook says to do %DWC3_DEPCMD_DEPSTARTCFG for every 54662306a36Sopenharmony_ci * %USB_REQ_SET_CONFIGURATION and %USB_REQ_SET_INTERFACE (8.1.5). This is 54762306a36Sopenharmony_ci * incorrect in the scenario of multiple interfaces. 54862306a36Sopenharmony_ci * 54962306a36Sopenharmony_ci * 2) The databook does not mention doing more %DWC3_DEPCMD_DEPXFERCFG for new 55062306a36Sopenharmony_ci * endpoint on alt setting (8.1.6). 55162306a36Sopenharmony_ci * 55262306a36Sopenharmony_ci * The following simplified method is used instead: 55362306a36Sopenharmony_ci * 55462306a36Sopenharmony_ci * All hardware endpoints can be assigned a transfer resource and this setting 55562306a36Sopenharmony_ci * will stay persistent until either a core reset or hibernation. So whenever we 55662306a36Sopenharmony_ci * do a %DWC3_DEPCMD_DEPSTARTCFG(0) we can go ahead and do 55762306a36Sopenharmony_ci * %DWC3_DEPCMD_DEPXFERCFG for every hardware endpoint as well. We are 55862306a36Sopenharmony_ci * guaranteed that there are as many transfer resources as endpoints. 55962306a36Sopenharmony_ci * 56062306a36Sopenharmony_ci * This function is called for each endpoint when it is being enabled but is 56162306a36Sopenharmony_ci * triggered only when called for EP0-out, which always happens first, and which 56262306a36Sopenharmony_ci * should only happen in one of the above conditions. 56362306a36Sopenharmony_ci */ 56462306a36Sopenharmony_cistatic int dwc3_gadget_start_config(struct dwc3_ep *dep) 56562306a36Sopenharmony_ci{ 56662306a36Sopenharmony_ci struct dwc3_gadget_ep_cmd_params params; 56762306a36Sopenharmony_ci struct dwc3 *dwc; 56862306a36Sopenharmony_ci u32 cmd; 56962306a36Sopenharmony_ci int i; 57062306a36Sopenharmony_ci int ret; 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci if (dep->number) 57362306a36Sopenharmony_ci return 0; 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci memset(¶ms, 0x00, sizeof(params)); 57662306a36Sopenharmony_ci cmd = DWC3_DEPCMD_DEPSTARTCFG; 57762306a36Sopenharmony_ci dwc = dep->dwc; 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms); 58062306a36Sopenharmony_ci if (ret) 58162306a36Sopenharmony_ci return ret; 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci for (i = 0; i < DWC3_ENDPOINTS_NUM; i++) { 58462306a36Sopenharmony_ci struct dwc3_ep *dep = dwc->eps[i]; 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci if (!dep) 58762306a36Sopenharmony_ci continue; 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci ret = dwc3_gadget_set_xfer_resource(dep); 59062306a36Sopenharmony_ci if (ret) 59162306a36Sopenharmony_ci return ret; 59262306a36Sopenharmony_ci } 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci return 0; 59562306a36Sopenharmony_ci} 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_cistatic int dwc3_gadget_set_ep_config(struct dwc3_ep *dep, unsigned int action) 59862306a36Sopenharmony_ci{ 59962306a36Sopenharmony_ci const struct usb_ss_ep_comp_descriptor *comp_desc; 60062306a36Sopenharmony_ci const struct usb_endpoint_descriptor *desc; 60162306a36Sopenharmony_ci struct dwc3_gadget_ep_cmd_params params; 60262306a36Sopenharmony_ci struct dwc3 *dwc = dep->dwc; 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci comp_desc = dep->endpoint.comp_desc; 60562306a36Sopenharmony_ci desc = dep->endpoint.desc; 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci memset(¶ms, 0x00, sizeof(params)); 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci params.param0 = DWC3_DEPCFG_EP_TYPE(usb_endpoint_type(desc)) 61062306a36Sopenharmony_ci | DWC3_DEPCFG_MAX_PACKET_SIZE(usb_endpoint_maxp(desc)); 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ci /* Burst size is only needed in SuperSpeed mode */ 61362306a36Sopenharmony_ci if (dwc->gadget->speed >= USB_SPEED_SUPER) { 61462306a36Sopenharmony_ci u32 burst = dep->endpoint.maxburst; 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci params.param0 |= DWC3_DEPCFG_BURST_SIZE(burst - 1); 61762306a36Sopenharmony_ci } 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci params.param0 |= action; 62062306a36Sopenharmony_ci if (action == DWC3_DEPCFG_ACTION_RESTORE) 62162306a36Sopenharmony_ci params.param2 |= dep->saved_state; 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci if (usb_endpoint_xfer_control(desc)) 62462306a36Sopenharmony_ci params.param1 = DWC3_DEPCFG_XFER_COMPLETE_EN; 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci if (dep->number <= 1 || usb_endpoint_xfer_isoc(desc)) 62762306a36Sopenharmony_ci params.param1 |= DWC3_DEPCFG_XFER_NOT_READY_EN; 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci if (usb_ss_max_streams(comp_desc) && usb_endpoint_xfer_bulk(desc)) { 63062306a36Sopenharmony_ci params.param1 |= DWC3_DEPCFG_STREAM_CAPABLE 63162306a36Sopenharmony_ci | DWC3_DEPCFG_XFER_COMPLETE_EN 63262306a36Sopenharmony_ci | DWC3_DEPCFG_STREAM_EVENT_EN; 63362306a36Sopenharmony_ci dep->stream_capable = true; 63462306a36Sopenharmony_ci } 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci if (!usb_endpoint_xfer_control(desc)) 63762306a36Sopenharmony_ci params.param1 |= DWC3_DEPCFG_XFER_IN_PROGRESS_EN; 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_ci /* 64062306a36Sopenharmony_ci * We are doing 1:1 mapping for endpoints, meaning 64162306a36Sopenharmony_ci * Physical Endpoints 2 maps to Logical Endpoint 2 and 64262306a36Sopenharmony_ci * so on. We consider the direction bit as part of the physical 64362306a36Sopenharmony_ci * endpoint number. So USB endpoint 0x81 is 0x03. 64462306a36Sopenharmony_ci */ 64562306a36Sopenharmony_ci params.param1 |= DWC3_DEPCFG_EP_NUMBER(dep->number); 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci /* 64862306a36Sopenharmony_ci * We must use the lower 16 TX FIFOs even though 64962306a36Sopenharmony_ci * HW might have more 65062306a36Sopenharmony_ci */ 65162306a36Sopenharmony_ci if (dep->direction) 65262306a36Sopenharmony_ci params.param0 |= DWC3_DEPCFG_FIFO_NUMBER(dep->number >> 1); 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci if (desc->bInterval) { 65562306a36Sopenharmony_ci u8 bInterval_m1; 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci /* 65862306a36Sopenharmony_ci * Valid range for DEPCFG.bInterval_m1 is from 0 to 13. 65962306a36Sopenharmony_ci * 66062306a36Sopenharmony_ci * NOTE: The programming guide incorrectly stated bInterval_m1 66162306a36Sopenharmony_ci * must be set to 0 when operating in fullspeed. Internally the 66262306a36Sopenharmony_ci * controller does not have this limitation. See DWC_usb3x 66362306a36Sopenharmony_ci * programming guide section 3.2.2.1. 66462306a36Sopenharmony_ci */ 66562306a36Sopenharmony_ci bInterval_m1 = min_t(u8, desc->bInterval - 1, 13); 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci if (usb_endpoint_type(desc) == USB_ENDPOINT_XFER_INT && 66862306a36Sopenharmony_ci dwc->gadget->speed == USB_SPEED_FULL) 66962306a36Sopenharmony_ci dep->interval = desc->bInterval; 67062306a36Sopenharmony_ci else 67162306a36Sopenharmony_ci dep->interval = 1 << (desc->bInterval - 1); 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci params.param1 |= DWC3_DEPCFG_BINTERVAL_M1(bInterval_m1); 67462306a36Sopenharmony_ci } 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci return dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_SETEPCONFIG, ¶ms); 67762306a36Sopenharmony_ci} 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci/** 68062306a36Sopenharmony_ci * dwc3_gadget_calc_tx_fifo_size - calculates the txfifo size value 68162306a36Sopenharmony_ci * @dwc: pointer to the DWC3 context 68262306a36Sopenharmony_ci * @mult: multiplier to be used when calculating the fifo_size 68362306a36Sopenharmony_ci * 68462306a36Sopenharmony_ci * Calculates the size value based on the equation below: 68562306a36Sopenharmony_ci * 68662306a36Sopenharmony_ci * DWC3 revision 280A and prior: 68762306a36Sopenharmony_ci * fifo_size = mult * (max_packet / mdwidth) + 1; 68862306a36Sopenharmony_ci * 68962306a36Sopenharmony_ci * DWC3 revision 290A and onwards: 69062306a36Sopenharmony_ci * fifo_size = mult * ((max_packet + mdwidth)/mdwidth + 1) + 1 69162306a36Sopenharmony_ci * 69262306a36Sopenharmony_ci * The max packet size is set to 1024, as the txfifo requirements mainly apply 69362306a36Sopenharmony_ci * to super speed USB use cases. However, it is safe to overestimate the fifo 69462306a36Sopenharmony_ci * allocations for other scenarios, i.e. high speed USB. 69562306a36Sopenharmony_ci */ 69662306a36Sopenharmony_cistatic int dwc3_gadget_calc_tx_fifo_size(struct dwc3 *dwc, int mult) 69762306a36Sopenharmony_ci{ 69862306a36Sopenharmony_ci int max_packet = 1024; 69962306a36Sopenharmony_ci int fifo_size; 70062306a36Sopenharmony_ci int mdwidth; 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci mdwidth = dwc3_mdwidth(dwc); 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci /* MDWIDTH is represented in bits, we need it in bytes */ 70562306a36Sopenharmony_ci mdwidth >>= 3; 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci if (DWC3_VER_IS_PRIOR(DWC3, 290A)) 70862306a36Sopenharmony_ci fifo_size = mult * (max_packet / mdwidth) + 1; 70962306a36Sopenharmony_ci else 71062306a36Sopenharmony_ci fifo_size = mult * ((max_packet + mdwidth) / mdwidth) + 1; 71162306a36Sopenharmony_ci return fifo_size; 71262306a36Sopenharmony_ci} 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci/** 71562306a36Sopenharmony_ci * dwc3_gadget_clear_tx_fifos - Clears txfifo allocation 71662306a36Sopenharmony_ci * @dwc: pointer to the DWC3 context 71762306a36Sopenharmony_ci * 71862306a36Sopenharmony_ci * Iterates through all the endpoint registers and clears the previous txfifo 71962306a36Sopenharmony_ci * allocations. 72062306a36Sopenharmony_ci */ 72162306a36Sopenharmony_civoid dwc3_gadget_clear_tx_fifos(struct dwc3 *dwc) 72262306a36Sopenharmony_ci{ 72362306a36Sopenharmony_ci struct dwc3_ep *dep; 72462306a36Sopenharmony_ci int fifo_depth; 72562306a36Sopenharmony_ci int size; 72662306a36Sopenharmony_ci int num; 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci if (!dwc->do_fifo_resize) 72962306a36Sopenharmony_ci return; 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci /* Read ep0IN related TXFIFO size */ 73262306a36Sopenharmony_ci dep = dwc->eps[1]; 73362306a36Sopenharmony_ci size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(0)); 73462306a36Sopenharmony_ci if (DWC3_IP_IS(DWC3)) 73562306a36Sopenharmony_ci fifo_depth = DWC3_GTXFIFOSIZ_TXFDEP(size); 73662306a36Sopenharmony_ci else 73762306a36Sopenharmony_ci fifo_depth = DWC31_GTXFIFOSIZ_TXFDEP(size); 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci dwc->last_fifo_depth = fifo_depth; 74062306a36Sopenharmony_ci /* Clear existing TXFIFO for all IN eps except ep0 */ 74162306a36Sopenharmony_ci for (num = 3; num < min_t(int, dwc->num_eps, DWC3_ENDPOINTS_NUM); 74262306a36Sopenharmony_ci num += 2) { 74362306a36Sopenharmony_ci dep = dwc->eps[num]; 74462306a36Sopenharmony_ci /* Don't change TXFRAMNUM on usb31 version */ 74562306a36Sopenharmony_ci size = DWC3_IP_IS(DWC3) ? 0 : 74662306a36Sopenharmony_ci dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(num >> 1)) & 74762306a36Sopenharmony_ci DWC31_GTXFIFOSIZ_TXFRAMNUM; 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(num >> 1), size); 75062306a36Sopenharmony_ci dep->flags &= ~DWC3_EP_TXFIFO_RESIZED; 75162306a36Sopenharmony_ci } 75262306a36Sopenharmony_ci dwc->num_ep_resized = 0; 75362306a36Sopenharmony_ci} 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci/* 75662306a36Sopenharmony_ci * dwc3_gadget_resize_tx_fifos - reallocate fifo spaces for current use-case 75762306a36Sopenharmony_ci * @dwc: pointer to our context structure 75862306a36Sopenharmony_ci * 75962306a36Sopenharmony_ci * This function will a best effort FIFO allocation in order 76062306a36Sopenharmony_ci * to improve FIFO usage and throughput, while still allowing 76162306a36Sopenharmony_ci * us to enable as many endpoints as possible. 76262306a36Sopenharmony_ci * 76362306a36Sopenharmony_ci * Keep in mind that this operation will be highly dependent 76462306a36Sopenharmony_ci * on the configured size for RAM1 - which contains TxFifo -, 76562306a36Sopenharmony_ci * the amount of endpoints enabled on coreConsultant tool, and 76662306a36Sopenharmony_ci * the width of the Master Bus. 76762306a36Sopenharmony_ci * 76862306a36Sopenharmony_ci * In general, FIFO depths are represented with the following equation: 76962306a36Sopenharmony_ci * 77062306a36Sopenharmony_ci * fifo_size = mult * ((max_packet + mdwidth)/mdwidth + 1) + 1 77162306a36Sopenharmony_ci * 77262306a36Sopenharmony_ci * In conjunction with dwc3_gadget_check_config(), this resizing logic will 77362306a36Sopenharmony_ci * ensure that all endpoints will have enough internal memory for one max 77462306a36Sopenharmony_ci * packet per endpoint. 77562306a36Sopenharmony_ci */ 77662306a36Sopenharmony_cistatic int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep) 77762306a36Sopenharmony_ci{ 77862306a36Sopenharmony_ci struct dwc3 *dwc = dep->dwc; 77962306a36Sopenharmony_ci int fifo_0_start; 78062306a36Sopenharmony_ci int ram1_depth; 78162306a36Sopenharmony_ci int fifo_size; 78262306a36Sopenharmony_ci int min_depth; 78362306a36Sopenharmony_ci int num_in_ep; 78462306a36Sopenharmony_ci int remaining; 78562306a36Sopenharmony_ci int num_fifos = 1; 78662306a36Sopenharmony_ci int fifo; 78762306a36Sopenharmony_ci int tmp; 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci if (!dwc->do_fifo_resize) 79062306a36Sopenharmony_ci return 0; 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci /* resize IN endpoints except ep0 */ 79362306a36Sopenharmony_ci if (!usb_endpoint_dir_in(dep->endpoint.desc) || dep->number <= 1) 79462306a36Sopenharmony_ci return 0; 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_ci /* bail if already resized */ 79762306a36Sopenharmony_ci if (dep->flags & DWC3_EP_TXFIFO_RESIZED) 79862306a36Sopenharmony_ci return 0; 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7); 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci if ((dep->endpoint.maxburst > 1 && 80362306a36Sopenharmony_ci usb_endpoint_xfer_bulk(dep->endpoint.desc)) || 80462306a36Sopenharmony_ci usb_endpoint_xfer_isoc(dep->endpoint.desc)) 80562306a36Sopenharmony_ci num_fifos = 3; 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci if (dep->endpoint.maxburst > 6 && 80862306a36Sopenharmony_ci (usb_endpoint_xfer_bulk(dep->endpoint.desc) || 80962306a36Sopenharmony_ci usb_endpoint_xfer_isoc(dep->endpoint.desc)) && DWC3_IP_IS(DWC31)) 81062306a36Sopenharmony_ci num_fifos = dwc->tx_fifo_resize_max_num; 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci /* FIFO size for a single buffer */ 81362306a36Sopenharmony_ci fifo = dwc3_gadget_calc_tx_fifo_size(dwc, 1); 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_ci /* Calculate the number of remaining EPs w/o any FIFO */ 81662306a36Sopenharmony_ci num_in_ep = dwc->max_cfg_eps; 81762306a36Sopenharmony_ci num_in_ep -= dwc->num_ep_resized; 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci /* Reserve at least one FIFO for the number of IN EPs */ 82062306a36Sopenharmony_ci min_depth = num_in_ep * (fifo + 1); 82162306a36Sopenharmony_ci remaining = ram1_depth - min_depth - dwc->last_fifo_depth; 82262306a36Sopenharmony_ci remaining = max_t(int, 0, remaining); 82362306a36Sopenharmony_ci /* 82462306a36Sopenharmony_ci * We've already reserved 1 FIFO per EP, so check what we can fit in 82562306a36Sopenharmony_ci * addition to it. If there is not enough remaining space, allocate 82662306a36Sopenharmony_ci * all the remaining space to the EP. 82762306a36Sopenharmony_ci */ 82862306a36Sopenharmony_ci fifo_size = (num_fifos - 1) * fifo; 82962306a36Sopenharmony_ci if (remaining < fifo_size) 83062306a36Sopenharmony_ci fifo_size = remaining; 83162306a36Sopenharmony_ci 83262306a36Sopenharmony_ci fifo_size += fifo; 83362306a36Sopenharmony_ci /* Last increment according to the TX FIFO size equation */ 83462306a36Sopenharmony_ci fifo_size++; 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_ci /* Check if TXFIFOs start at non-zero addr */ 83762306a36Sopenharmony_ci tmp = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(0)); 83862306a36Sopenharmony_ci fifo_0_start = DWC3_GTXFIFOSIZ_TXFSTADDR(tmp); 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_ci fifo_size |= (fifo_0_start + (dwc->last_fifo_depth << 16)); 84162306a36Sopenharmony_ci if (DWC3_IP_IS(DWC3)) 84262306a36Sopenharmony_ci dwc->last_fifo_depth += DWC3_GTXFIFOSIZ_TXFDEP(fifo_size); 84362306a36Sopenharmony_ci else 84462306a36Sopenharmony_ci dwc->last_fifo_depth += DWC31_GTXFIFOSIZ_TXFDEP(fifo_size); 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_ci /* Check fifo size allocation doesn't exceed available RAM size. */ 84762306a36Sopenharmony_ci if (dwc->last_fifo_depth >= ram1_depth) { 84862306a36Sopenharmony_ci dev_err(dwc->dev, "Fifosize(%d) > RAM size(%d) %s depth:%d\n", 84962306a36Sopenharmony_ci dwc->last_fifo_depth, ram1_depth, 85062306a36Sopenharmony_ci dep->endpoint.name, fifo_size); 85162306a36Sopenharmony_ci if (DWC3_IP_IS(DWC3)) 85262306a36Sopenharmony_ci fifo_size = DWC3_GTXFIFOSIZ_TXFDEP(fifo_size); 85362306a36Sopenharmony_ci else 85462306a36Sopenharmony_ci fifo_size = DWC31_GTXFIFOSIZ_TXFDEP(fifo_size); 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_ci dwc->last_fifo_depth -= fifo_size; 85762306a36Sopenharmony_ci return -ENOMEM; 85862306a36Sopenharmony_ci } 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(dep->number >> 1), fifo_size); 86162306a36Sopenharmony_ci dep->flags |= DWC3_EP_TXFIFO_RESIZED; 86262306a36Sopenharmony_ci dwc->num_ep_resized++; 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ci return 0; 86562306a36Sopenharmony_ci} 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_ci/** 86862306a36Sopenharmony_ci * __dwc3_gadget_ep_enable - initializes a hw endpoint 86962306a36Sopenharmony_ci * @dep: endpoint to be initialized 87062306a36Sopenharmony_ci * @action: one of INIT, MODIFY or RESTORE 87162306a36Sopenharmony_ci * 87262306a36Sopenharmony_ci * Caller should take care of locking. Execute all necessary commands to 87362306a36Sopenharmony_ci * initialize a HW endpoint so it can be used by a gadget driver. 87462306a36Sopenharmony_ci */ 87562306a36Sopenharmony_cistatic int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action) 87662306a36Sopenharmony_ci{ 87762306a36Sopenharmony_ci const struct usb_endpoint_descriptor *desc = dep->endpoint.desc; 87862306a36Sopenharmony_ci struct dwc3 *dwc = dep->dwc; 87962306a36Sopenharmony_ci 88062306a36Sopenharmony_ci u32 reg; 88162306a36Sopenharmony_ci int ret; 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci if (!(dep->flags & DWC3_EP_ENABLED)) { 88462306a36Sopenharmony_ci ret = dwc3_gadget_resize_tx_fifos(dep); 88562306a36Sopenharmony_ci if (ret) 88662306a36Sopenharmony_ci return ret; 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_ci ret = dwc3_gadget_start_config(dep); 88962306a36Sopenharmony_ci if (ret) 89062306a36Sopenharmony_ci return ret; 89162306a36Sopenharmony_ci } 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_ci ret = dwc3_gadget_set_ep_config(dep, action); 89462306a36Sopenharmony_ci if (ret) 89562306a36Sopenharmony_ci return ret; 89662306a36Sopenharmony_ci 89762306a36Sopenharmony_ci if (!(dep->flags & DWC3_EP_ENABLED)) { 89862306a36Sopenharmony_ci struct dwc3_trb *trb_st_hw; 89962306a36Sopenharmony_ci struct dwc3_trb *trb_link; 90062306a36Sopenharmony_ci 90162306a36Sopenharmony_ci dep->type = usb_endpoint_type(desc); 90262306a36Sopenharmony_ci dep->flags |= DWC3_EP_ENABLED; 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_DALEPENA); 90562306a36Sopenharmony_ci reg |= DWC3_DALEPENA_EP(dep->number); 90662306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_ci dep->trb_dequeue = 0; 90962306a36Sopenharmony_ci dep->trb_enqueue = 0; 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_ci if (usb_endpoint_xfer_control(desc)) 91262306a36Sopenharmony_ci goto out; 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_ci /* Initialize the TRB ring */ 91562306a36Sopenharmony_ci memset(dep->trb_pool, 0, 91662306a36Sopenharmony_ci sizeof(struct dwc3_trb) * DWC3_TRB_NUM); 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_ci /* Link TRB. The HWO bit is never reset */ 91962306a36Sopenharmony_ci trb_st_hw = &dep->trb_pool[0]; 92062306a36Sopenharmony_ci 92162306a36Sopenharmony_ci trb_link = &dep->trb_pool[DWC3_TRB_NUM - 1]; 92262306a36Sopenharmony_ci trb_link->bpl = lower_32_bits(dwc3_trb_dma_offset(dep, trb_st_hw)); 92362306a36Sopenharmony_ci trb_link->bph = upper_32_bits(dwc3_trb_dma_offset(dep, trb_st_hw)); 92462306a36Sopenharmony_ci trb_link->ctrl |= DWC3_TRBCTL_LINK_TRB; 92562306a36Sopenharmony_ci trb_link->ctrl |= DWC3_TRB_CTRL_HWO; 92662306a36Sopenharmony_ci } 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci /* 92962306a36Sopenharmony_ci * Issue StartTransfer here with no-op TRB so we can always rely on No 93062306a36Sopenharmony_ci * Response Update Transfer command. 93162306a36Sopenharmony_ci */ 93262306a36Sopenharmony_ci if (usb_endpoint_xfer_bulk(desc) || 93362306a36Sopenharmony_ci usb_endpoint_xfer_int(desc)) { 93462306a36Sopenharmony_ci struct dwc3_gadget_ep_cmd_params params; 93562306a36Sopenharmony_ci struct dwc3_trb *trb; 93662306a36Sopenharmony_ci dma_addr_t trb_dma; 93762306a36Sopenharmony_ci u32 cmd; 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_ci memset(¶ms, 0, sizeof(params)); 94062306a36Sopenharmony_ci trb = &dep->trb_pool[0]; 94162306a36Sopenharmony_ci trb_dma = dwc3_trb_dma_offset(dep, trb); 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_ci params.param0 = upper_32_bits(trb_dma); 94462306a36Sopenharmony_ci params.param1 = lower_32_bits(trb_dma); 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_ci cmd = DWC3_DEPCMD_STARTTRANSFER; 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_ci ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms); 94962306a36Sopenharmony_ci if (ret < 0) 95062306a36Sopenharmony_ci return ret; 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_ci if (dep->stream_capable) { 95362306a36Sopenharmony_ci /* 95462306a36Sopenharmony_ci * For streams, at start, there maybe a race where the 95562306a36Sopenharmony_ci * host primes the endpoint before the function driver 95662306a36Sopenharmony_ci * queues a request to initiate a stream. In that case, 95762306a36Sopenharmony_ci * the controller will not see the prime to generate the 95862306a36Sopenharmony_ci * ERDY and start stream. To workaround this, issue a 95962306a36Sopenharmony_ci * no-op TRB as normal, but end it immediately. As a 96062306a36Sopenharmony_ci * result, when the function driver queues the request, 96162306a36Sopenharmony_ci * the next START_TRANSFER command will cause the 96262306a36Sopenharmony_ci * controller to generate an ERDY to initiate the 96362306a36Sopenharmony_ci * stream. 96462306a36Sopenharmony_ci */ 96562306a36Sopenharmony_ci dwc3_stop_active_transfer(dep, true, true); 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_ci /* 96862306a36Sopenharmony_ci * All stream eps will reinitiate stream on NoStream 96962306a36Sopenharmony_ci * rejection until we can determine that the host can 97062306a36Sopenharmony_ci * prime after the first transfer. 97162306a36Sopenharmony_ci * 97262306a36Sopenharmony_ci * However, if the controller is capable of 97362306a36Sopenharmony_ci * TXF_FLUSH_BYPASS, then IN direction endpoints will 97462306a36Sopenharmony_ci * automatically restart the stream without the driver 97562306a36Sopenharmony_ci * initiation. 97662306a36Sopenharmony_ci */ 97762306a36Sopenharmony_ci if (!dep->direction || 97862306a36Sopenharmony_ci !(dwc->hwparams.hwparams9 & 97962306a36Sopenharmony_ci DWC3_GHWPARAMS9_DEV_TXF_FLUSH_BYPASS)) 98062306a36Sopenharmony_ci dep->flags |= DWC3_EP_FORCE_RESTART_STREAM; 98162306a36Sopenharmony_ci } 98262306a36Sopenharmony_ci } 98362306a36Sopenharmony_ci 98462306a36Sopenharmony_ciout: 98562306a36Sopenharmony_ci trace_dwc3_gadget_ep_enable(dep); 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_ci return 0; 98862306a36Sopenharmony_ci} 98962306a36Sopenharmony_ci 99062306a36Sopenharmony_civoid dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep, int status) 99162306a36Sopenharmony_ci{ 99262306a36Sopenharmony_ci struct dwc3_request *req; 99362306a36Sopenharmony_ci 99462306a36Sopenharmony_ci dwc3_stop_active_transfer(dep, true, false); 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_ci /* If endxfer is delayed, avoid unmapping requests */ 99762306a36Sopenharmony_ci if (dep->flags & DWC3_EP_DELAY_STOP) 99862306a36Sopenharmony_ci return; 99962306a36Sopenharmony_ci 100062306a36Sopenharmony_ci /* - giveback all requests to gadget driver */ 100162306a36Sopenharmony_ci while (!list_empty(&dep->started_list)) { 100262306a36Sopenharmony_ci req = next_request(&dep->started_list); 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_ci dwc3_gadget_giveback(dep, req, status); 100562306a36Sopenharmony_ci } 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ci while (!list_empty(&dep->pending_list)) { 100862306a36Sopenharmony_ci req = next_request(&dep->pending_list); 100962306a36Sopenharmony_ci 101062306a36Sopenharmony_ci dwc3_gadget_giveback(dep, req, status); 101162306a36Sopenharmony_ci } 101262306a36Sopenharmony_ci 101362306a36Sopenharmony_ci while (!list_empty(&dep->cancelled_list)) { 101462306a36Sopenharmony_ci req = next_request(&dep->cancelled_list); 101562306a36Sopenharmony_ci 101662306a36Sopenharmony_ci dwc3_gadget_giveback(dep, req, status); 101762306a36Sopenharmony_ci } 101862306a36Sopenharmony_ci} 101962306a36Sopenharmony_ci 102062306a36Sopenharmony_ci/** 102162306a36Sopenharmony_ci * __dwc3_gadget_ep_disable - disables a hw endpoint 102262306a36Sopenharmony_ci * @dep: the endpoint to disable 102362306a36Sopenharmony_ci * 102462306a36Sopenharmony_ci * This function undoes what __dwc3_gadget_ep_enable did and also removes 102562306a36Sopenharmony_ci * requests which are currently being processed by the hardware and those which 102662306a36Sopenharmony_ci * are not yet scheduled. 102762306a36Sopenharmony_ci * 102862306a36Sopenharmony_ci * Caller should take care of locking. 102962306a36Sopenharmony_ci */ 103062306a36Sopenharmony_cistatic int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) 103162306a36Sopenharmony_ci{ 103262306a36Sopenharmony_ci struct dwc3 *dwc = dep->dwc; 103362306a36Sopenharmony_ci u32 reg; 103462306a36Sopenharmony_ci u32 mask; 103562306a36Sopenharmony_ci 103662306a36Sopenharmony_ci trace_dwc3_gadget_ep_disable(dep); 103762306a36Sopenharmony_ci 103862306a36Sopenharmony_ci /* make sure HW endpoint isn't stalled */ 103962306a36Sopenharmony_ci if (dep->flags & DWC3_EP_STALL) 104062306a36Sopenharmony_ci __dwc3_gadget_ep_set_halt(dep, 0, false); 104162306a36Sopenharmony_ci 104262306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_DALEPENA); 104362306a36Sopenharmony_ci reg &= ~DWC3_DALEPENA_EP(dep->number); 104462306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); 104562306a36Sopenharmony_ci 104662306a36Sopenharmony_ci dwc3_remove_requests(dwc, dep, -ESHUTDOWN); 104762306a36Sopenharmony_ci 104862306a36Sopenharmony_ci dep->stream_capable = false; 104962306a36Sopenharmony_ci dep->type = 0; 105062306a36Sopenharmony_ci mask = DWC3_EP_TXFIFO_RESIZED; 105162306a36Sopenharmony_ci /* 105262306a36Sopenharmony_ci * dwc3_remove_requests() can exit early if DWC3 EP delayed stop is 105362306a36Sopenharmony_ci * set. Do not clear DEP flags, so that the end transfer command will 105462306a36Sopenharmony_ci * be reattempted during the next SETUP stage. 105562306a36Sopenharmony_ci */ 105662306a36Sopenharmony_ci if (dep->flags & DWC3_EP_DELAY_STOP) 105762306a36Sopenharmony_ci mask |= (DWC3_EP_DELAY_STOP | DWC3_EP_TRANSFER_STARTED); 105862306a36Sopenharmony_ci dep->flags &= mask; 105962306a36Sopenharmony_ci 106062306a36Sopenharmony_ci /* Clear out the ep descriptors for non-ep0 */ 106162306a36Sopenharmony_ci if (dep->number > 1) { 106262306a36Sopenharmony_ci dep->endpoint.comp_desc = NULL; 106362306a36Sopenharmony_ci dep->endpoint.desc = NULL; 106462306a36Sopenharmony_ci } 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_ci return 0; 106762306a36Sopenharmony_ci} 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_ci/* -------------------------------------------------------------------------- */ 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_cistatic int dwc3_gadget_ep0_enable(struct usb_ep *ep, 107262306a36Sopenharmony_ci const struct usb_endpoint_descriptor *desc) 107362306a36Sopenharmony_ci{ 107462306a36Sopenharmony_ci return -EINVAL; 107562306a36Sopenharmony_ci} 107662306a36Sopenharmony_ci 107762306a36Sopenharmony_cistatic int dwc3_gadget_ep0_disable(struct usb_ep *ep) 107862306a36Sopenharmony_ci{ 107962306a36Sopenharmony_ci return -EINVAL; 108062306a36Sopenharmony_ci} 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_ci/* -------------------------------------------------------------------------- */ 108362306a36Sopenharmony_ci 108462306a36Sopenharmony_cistatic int dwc3_gadget_ep_enable(struct usb_ep *ep, 108562306a36Sopenharmony_ci const struct usb_endpoint_descriptor *desc) 108662306a36Sopenharmony_ci{ 108762306a36Sopenharmony_ci struct dwc3_ep *dep; 108862306a36Sopenharmony_ci struct dwc3 *dwc; 108962306a36Sopenharmony_ci unsigned long flags; 109062306a36Sopenharmony_ci int ret; 109162306a36Sopenharmony_ci 109262306a36Sopenharmony_ci if (!ep || !desc || desc->bDescriptorType != USB_DT_ENDPOINT) { 109362306a36Sopenharmony_ci pr_debug("dwc3: invalid parameters\n"); 109462306a36Sopenharmony_ci return -EINVAL; 109562306a36Sopenharmony_ci } 109662306a36Sopenharmony_ci 109762306a36Sopenharmony_ci if (!desc->wMaxPacketSize) { 109862306a36Sopenharmony_ci pr_debug("dwc3: missing wMaxPacketSize\n"); 109962306a36Sopenharmony_ci return -EINVAL; 110062306a36Sopenharmony_ci } 110162306a36Sopenharmony_ci 110262306a36Sopenharmony_ci dep = to_dwc3_ep(ep); 110362306a36Sopenharmony_ci dwc = dep->dwc; 110462306a36Sopenharmony_ci 110562306a36Sopenharmony_ci if (dev_WARN_ONCE(dwc->dev, dep->flags & DWC3_EP_ENABLED, 110662306a36Sopenharmony_ci "%s is already enabled\n", 110762306a36Sopenharmony_ci dep->name)) 110862306a36Sopenharmony_ci return 0; 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_ci spin_lock_irqsave(&dwc->lock, flags); 111162306a36Sopenharmony_ci ret = __dwc3_gadget_ep_enable(dep, DWC3_DEPCFG_ACTION_INIT); 111262306a36Sopenharmony_ci spin_unlock_irqrestore(&dwc->lock, flags); 111362306a36Sopenharmony_ci 111462306a36Sopenharmony_ci return ret; 111562306a36Sopenharmony_ci} 111662306a36Sopenharmony_ci 111762306a36Sopenharmony_cistatic int dwc3_gadget_ep_disable(struct usb_ep *ep) 111862306a36Sopenharmony_ci{ 111962306a36Sopenharmony_ci struct dwc3_ep *dep; 112062306a36Sopenharmony_ci struct dwc3 *dwc; 112162306a36Sopenharmony_ci unsigned long flags; 112262306a36Sopenharmony_ci int ret; 112362306a36Sopenharmony_ci 112462306a36Sopenharmony_ci if (!ep) { 112562306a36Sopenharmony_ci pr_debug("dwc3: invalid parameters\n"); 112662306a36Sopenharmony_ci return -EINVAL; 112762306a36Sopenharmony_ci } 112862306a36Sopenharmony_ci 112962306a36Sopenharmony_ci dep = to_dwc3_ep(ep); 113062306a36Sopenharmony_ci dwc = dep->dwc; 113162306a36Sopenharmony_ci 113262306a36Sopenharmony_ci if (dev_WARN_ONCE(dwc->dev, !(dep->flags & DWC3_EP_ENABLED), 113362306a36Sopenharmony_ci "%s is already disabled\n", 113462306a36Sopenharmony_ci dep->name)) 113562306a36Sopenharmony_ci return 0; 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_ci spin_lock_irqsave(&dwc->lock, flags); 113862306a36Sopenharmony_ci ret = __dwc3_gadget_ep_disable(dep); 113962306a36Sopenharmony_ci spin_unlock_irqrestore(&dwc->lock, flags); 114062306a36Sopenharmony_ci 114162306a36Sopenharmony_ci return ret; 114262306a36Sopenharmony_ci} 114362306a36Sopenharmony_ci 114462306a36Sopenharmony_cistatic struct usb_request *dwc3_gadget_ep_alloc_request(struct usb_ep *ep, 114562306a36Sopenharmony_ci gfp_t gfp_flags) 114662306a36Sopenharmony_ci{ 114762306a36Sopenharmony_ci struct dwc3_request *req; 114862306a36Sopenharmony_ci struct dwc3_ep *dep = to_dwc3_ep(ep); 114962306a36Sopenharmony_ci 115062306a36Sopenharmony_ci req = kzalloc(sizeof(*req), gfp_flags); 115162306a36Sopenharmony_ci if (!req) 115262306a36Sopenharmony_ci return NULL; 115362306a36Sopenharmony_ci 115462306a36Sopenharmony_ci req->direction = dep->direction; 115562306a36Sopenharmony_ci req->epnum = dep->number; 115662306a36Sopenharmony_ci req->dep = dep; 115762306a36Sopenharmony_ci req->status = DWC3_REQUEST_STATUS_UNKNOWN; 115862306a36Sopenharmony_ci 115962306a36Sopenharmony_ci trace_dwc3_alloc_request(req); 116062306a36Sopenharmony_ci 116162306a36Sopenharmony_ci return &req->request; 116262306a36Sopenharmony_ci} 116362306a36Sopenharmony_ci 116462306a36Sopenharmony_cistatic void dwc3_gadget_ep_free_request(struct usb_ep *ep, 116562306a36Sopenharmony_ci struct usb_request *request) 116662306a36Sopenharmony_ci{ 116762306a36Sopenharmony_ci struct dwc3_request *req = to_dwc3_request(request); 116862306a36Sopenharmony_ci 116962306a36Sopenharmony_ci trace_dwc3_free_request(req); 117062306a36Sopenharmony_ci kfree(req); 117162306a36Sopenharmony_ci} 117262306a36Sopenharmony_ci 117362306a36Sopenharmony_ci/** 117462306a36Sopenharmony_ci * dwc3_ep_prev_trb - returns the previous TRB in the ring 117562306a36Sopenharmony_ci * @dep: The endpoint with the TRB ring 117662306a36Sopenharmony_ci * @index: The index of the current TRB in the ring 117762306a36Sopenharmony_ci * 117862306a36Sopenharmony_ci * Returns the TRB prior to the one pointed to by the index. If the 117962306a36Sopenharmony_ci * index is 0, we will wrap backwards, skip the link TRB, and return 118062306a36Sopenharmony_ci * the one just before that. 118162306a36Sopenharmony_ci */ 118262306a36Sopenharmony_cistatic struct dwc3_trb *dwc3_ep_prev_trb(struct dwc3_ep *dep, u8 index) 118362306a36Sopenharmony_ci{ 118462306a36Sopenharmony_ci u8 tmp = index; 118562306a36Sopenharmony_ci 118662306a36Sopenharmony_ci if (!tmp) 118762306a36Sopenharmony_ci tmp = DWC3_TRB_NUM - 1; 118862306a36Sopenharmony_ci 118962306a36Sopenharmony_ci return &dep->trb_pool[tmp - 1]; 119062306a36Sopenharmony_ci} 119162306a36Sopenharmony_ci 119262306a36Sopenharmony_cistatic u32 dwc3_calc_trbs_left(struct dwc3_ep *dep) 119362306a36Sopenharmony_ci{ 119462306a36Sopenharmony_ci u8 trbs_left; 119562306a36Sopenharmony_ci 119662306a36Sopenharmony_ci /* 119762306a36Sopenharmony_ci * If the enqueue & dequeue are equal then the TRB ring is either full 119862306a36Sopenharmony_ci * or empty. It's considered full when there are DWC3_TRB_NUM-1 of TRBs 119962306a36Sopenharmony_ci * pending to be processed by the driver. 120062306a36Sopenharmony_ci */ 120162306a36Sopenharmony_ci if (dep->trb_enqueue == dep->trb_dequeue) { 120262306a36Sopenharmony_ci /* 120362306a36Sopenharmony_ci * If there is any request remained in the started_list at 120462306a36Sopenharmony_ci * this point, that means there is no TRB available. 120562306a36Sopenharmony_ci */ 120662306a36Sopenharmony_ci if (!list_empty(&dep->started_list)) 120762306a36Sopenharmony_ci return 0; 120862306a36Sopenharmony_ci 120962306a36Sopenharmony_ci return DWC3_TRB_NUM - 1; 121062306a36Sopenharmony_ci } 121162306a36Sopenharmony_ci 121262306a36Sopenharmony_ci trbs_left = dep->trb_dequeue - dep->trb_enqueue; 121362306a36Sopenharmony_ci trbs_left &= (DWC3_TRB_NUM - 1); 121462306a36Sopenharmony_ci 121562306a36Sopenharmony_ci if (dep->trb_dequeue < dep->trb_enqueue) 121662306a36Sopenharmony_ci trbs_left--; 121762306a36Sopenharmony_ci 121862306a36Sopenharmony_ci return trbs_left; 121962306a36Sopenharmony_ci} 122062306a36Sopenharmony_ci 122162306a36Sopenharmony_ci/** 122262306a36Sopenharmony_ci * dwc3_prepare_one_trb - setup one TRB from one request 122362306a36Sopenharmony_ci * @dep: endpoint for which this request is prepared 122462306a36Sopenharmony_ci * @req: dwc3_request pointer 122562306a36Sopenharmony_ci * @trb_length: buffer size of the TRB 122662306a36Sopenharmony_ci * @chain: should this TRB be chained to the next? 122762306a36Sopenharmony_ci * @node: only for isochronous endpoints. First TRB needs different type. 122862306a36Sopenharmony_ci * @use_bounce_buffer: set to use bounce buffer 122962306a36Sopenharmony_ci * @must_interrupt: set to interrupt on TRB completion 123062306a36Sopenharmony_ci */ 123162306a36Sopenharmony_cistatic void dwc3_prepare_one_trb(struct dwc3_ep *dep, 123262306a36Sopenharmony_ci struct dwc3_request *req, unsigned int trb_length, 123362306a36Sopenharmony_ci unsigned int chain, unsigned int node, bool use_bounce_buffer, 123462306a36Sopenharmony_ci bool must_interrupt) 123562306a36Sopenharmony_ci{ 123662306a36Sopenharmony_ci struct dwc3_trb *trb; 123762306a36Sopenharmony_ci dma_addr_t dma; 123862306a36Sopenharmony_ci unsigned int stream_id = req->request.stream_id; 123962306a36Sopenharmony_ci unsigned int short_not_ok = req->request.short_not_ok; 124062306a36Sopenharmony_ci unsigned int no_interrupt = req->request.no_interrupt; 124162306a36Sopenharmony_ci unsigned int is_last = req->request.is_last; 124262306a36Sopenharmony_ci struct dwc3 *dwc = dep->dwc; 124362306a36Sopenharmony_ci struct usb_gadget *gadget = dwc->gadget; 124462306a36Sopenharmony_ci enum usb_device_speed speed = gadget->speed; 124562306a36Sopenharmony_ci 124662306a36Sopenharmony_ci if (use_bounce_buffer) 124762306a36Sopenharmony_ci dma = dep->dwc->bounce_addr; 124862306a36Sopenharmony_ci else if (req->request.num_sgs > 0) 124962306a36Sopenharmony_ci dma = sg_dma_address(req->start_sg); 125062306a36Sopenharmony_ci else 125162306a36Sopenharmony_ci dma = req->request.dma; 125262306a36Sopenharmony_ci 125362306a36Sopenharmony_ci trb = &dep->trb_pool[dep->trb_enqueue]; 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_ci if (!req->trb) { 125662306a36Sopenharmony_ci dwc3_gadget_move_started_request(req); 125762306a36Sopenharmony_ci req->trb = trb; 125862306a36Sopenharmony_ci req->trb_dma = dwc3_trb_dma_offset(dep, trb); 125962306a36Sopenharmony_ci } 126062306a36Sopenharmony_ci 126162306a36Sopenharmony_ci req->num_trbs++; 126262306a36Sopenharmony_ci 126362306a36Sopenharmony_ci trb->size = DWC3_TRB_SIZE_LENGTH(trb_length); 126462306a36Sopenharmony_ci trb->bpl = lower_32_bits(dma); 126562306a36Sopenharmony_ci trb->bph = upper_32_bits(dma); 126662306a36Sopenharmony_ci 126762306a36Sopenharmony_ci switch (usb_endpoint_type(dep->endpoint.desc)) { 126862306a36Sopenharmony_ci case USB_ENDPOINT_XFER_CONTROL: 126962306a36Sopenharmony_ci trb->ctrl = DWC3_TRBCTL_CONTROL_SETUP; 127062306a36Sopenharmony_ci break; 127162306a36Sopenharmony_ci 127262306a36Sopenharmony_ci case USB_ENDPOINT_XFER_ISOC: 127362306a36Sopenharmony_ci if (!node) { 127462306a36Sopenharmony_ci trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS_FIRST; 127562306a36Sopenharmony_ci 127662306a36Sopenharmony_ci /* 127762306a36Sopenharmony_ci * USB Specification 2.0 Section 5.9.2 states that: "If 127862306a36Sopenharmony_ci * there is only a single transaction in the microframe, 127962306a36Sopenharmony_ci * only a DATA0 data packet PID is used. If there are 128062306a36Sopenharmony_ci * two transactions per microframe, DATA1 is used for 128162306a36Sopenharmony_ci * the first transaction data packet and DATA0 is used 128262306a36Sopenharmony_ci * for the second transaction data packet. If there are 128362306a36Sopenharmony_ci * three transactions per microframe, DATA2 is used for 128462306a36Sopenharmony_ci * the first transaction data packet, DATA1 is used for 128562306a36Sopenharmony_ci * the second, and DATA0 is used for the third." 128662306a36Sopenharmony_ci * 128762306a36Sopenharmony_ci * IOW, we should satisfy the following cases: 128862306a36Sopenharmony_ci * 128962306a36Sopenharmony_ci * 1) length <= maxpacket 129062306a36Sopenharmony_ci * - DATA0 129162306a36Sopenharmony_ci * 129262306a36Sopenharmony_ci * 2) maxpacket < length <= (2 * maxpacket) 129362306a36Sopenharmony_ci * - DATA1, DATA0 129462306a36Sopenharmony_ci * 129562306a36Sopenharmony_ci * 3) (2 * maxpacket) < length <= (3 * maxpacket) 129662306a36Sopenharmony_ci * - DATA2, DATA1, DATA0 129762306a36Sopenharmony_ci */ 129862306a36Sopenharmony_ci if (speed == USB_SPEED_HIGH) { 129962306a36Sopenharmony_ci struct usb_ep *ep = &dep->endpoint; 130062306a36Sopenharmony_ci unsigned int mult = 2; 130162306a36Sopenharmony_ci unsigned int maxp = usb_endpoint_maxp(ep->desc); 130262306a36Sopenharmony_ci 130362306a36Sopenharmony_ci if (req->request.length <= (2 * maxp)) 130462306a36Sopenharmony_ci mult--; 130562306a36Sopenharmony_ci 130662306a36Sopenharmony_ci if (req->request.length <= maxp) 130762306a36Sopenharmony_ci mult--; 130862306a36Sopenharmony_ci 130962306a36Sopenharmony_ci trb->size |= DWC3_TRB_SIZE_PCM1(mult); 131062306a36Sopenharmony_ci } 131162306a36Sopenharmony_ci } else { 131262306a36Sopenharmony_ci trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS; 131362306a36Sopenharmony_ci } 131462306a36Sopenharmony_ci 131562306a36Sopenharmony_ci if (!no_interrupt && !chain) 131662306a36Sopenharmony_ci trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI; 131762306a36Sopenharmony_ci break; 131862306a36Sopenharmony_ci 131962306a36Sopenharmony_ci case USB_ENDPOINT_XFER_BULK: 132062306a36Sopenharmony_ci case USB_ENDPOINT_XFER_INT: 132162306a36Sopenharmony_ci trb->ctrl = DWC3_TRBCTL_NORMAL; 132262306a36Sopenharmony_ci break; 132362306a36Sopenharmony_ci default: 132462306a36Sopenharmony_ci /* 132562306a36Sopenharmony_ci * This is only possible with faulty memory because we 132662306a36Sopenharmony_ci * checked it already :) 132762306a36Sopenharmony_ci */ 132862306a36Sopenharmony_ci dev_WARN(dwc->dev, "Unknown endpoint type %d\n", 132962306a36Sopenharmony_ci usb_endpoint_type(dep->endpoint.desc)); 133062306a36Sopenharmony_ci } 133162306a36Sopenharmony_ci 133262306a36Sopenharmony_ci /* 133362306a36Sopenharmony_ci * Enable Continue on Short Packet 133462306a36Sopenharmony_ci * when endpoint is not a stream capable 133562306a36Sopenharmony_ci */ 133662306a36Sopenharmony_ci if (usb_endpoint_dir_out(dep->endpoint.desc)) { 133762306a36Sopenharmony_ci if (!dep->stream_capable) 133862306a36Sopenharmony_ci trb->ctrl |= DWC3_TRB_CTRL_CSP; 133962306a36Sopenharmony_ci 134062306a36Sopenharmony_ci if (short_not_ok) 134162306a36Sopenharmony_ci trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI; 134262306a36Sopenharmony_ci } 134362306a36Sopenharmony_ci 134462306a36Sopenharmony_ci /* All TRBs setup for MST must set CSP=1 when LST=0 */ 134562306a36Sopenharmony_ci if (dep->stream_capable && DWC3_MST_CAPABLE(&dwc->hwparams)) 134662306a36Sopenharmony_ci trb->ctrl |= DWC3_TRB_CTRL_CSP; 134762306a36Sopenharmony_ci 134862306a36Sopenharmony_ci if ((!no_interrupt && !chain) || must_interrupt) 134962306a36Sopenharmony_ci trb->ctrl |= DWC3_TRB_CTRL_IOC; 135062306a36Sopenharmony_ci 135162306a36Sopenharmony_ci if (chain) 135262306a36Sopenharmony_ci trb->ctrl |= DWC3_TRB_CTRL_CHN; 135362306a36Sopenharmony_ci else if (dep->stream_capable && is_last && 135462306a36Sopenharmony_ci !DWC3_MST_CAPABLE(&dwc->hwparams)) 135562306a36Sopenharmony_ci trb->ctrl |= DWC3_TRB_CTRL_LST; 135662306a36Sopenharmony_ci 135762306a36Sopenharmony_ci if (usb_endpoint_xfer_bulk(dep->endpoint.desc) && dep->stream_capable) 135862306a36Sopenharmony_ci trb->ctrl |= DWC3_TRB_CTRL_SID_SOFN(stream_id); 135962306a36Sopenharmony_ci 136062306a36Sopenharmony_ci /* 136162306a36Sopenharmony_ci * As per data book 4.2.3.2TRB Control Bit Rules section 136262306a36Sopenharmony_ci * 136362306a36Sopenharmony_ci * The controller autonomously checks the HWO field of a TRB to determine if the 136462306a36Sopenharmony_ci * entire TRB is valid. Therefore, software must ensure that the rest of the TRB 136562306a36Sopenharmony_ci * is valid before setting the HWO field to '1'. In most systems, this means that 136662306a36Sopenharmony_ci * software must update the fourth DWORD of a TRB last. 136762306a36Sopenharmony_ci * 136862306a36Sopenharmony_ci * However there is a possibility of CPU re-ordering here which can cause 136962306a36Sopenharmony_ci * controller to observe the HWO bit set prematurely. 137062306a36Sopenharmony_ci * Add a write memory barrier to prevent CPU re-ordering. 137162306a36Sopenharmony_ci */ 137262306a36Sopenharmony_ci wmb(); 137362306a36Sopenharmony_ci trb->ctrl |= DWC3_TRB_CTRL_HWO; 137462306a36Sopenharmony_ci 137562306a36Sopenharmony_ci dwc3_ep_inc_enq(dep); 137662306a36Sopenharmony_ci 137762306a36Sopenharmony_ci trace_dwc3_prepare_trb(dep, trb); 137862306a36Sopenharmony_ci} 137962306a36Sopenharmony_ci 138062306a36Sopenharmony_cistatic bool dwc3_needs_extra_trb(struct dwc3_ep *dep, struct dwc3_request *req) 138162306a36Sopenharmony_ci{ 138262306a36Sopenharmony_ci unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc); 138362306a36Sopenharmony_ci unsigned int rem = req->request.length % maxp; 138462306a36Sopenharmony_ci 138562306a36Sopenharmony_ci if ((req->request.length && req->request.zero && !rem && 138662306a36Sopenharmony_ci !usb_endpoint_xfer_isoc(dep->endpoint.desc)) || 138762306a36Sopenharmony_ci (!req->direction && rem)) 138862306a36Sopenharmony_ci return true; 138962306a36Sopenharmony_ci 139062306a36Sopenharmony_ci return false; 139162306a36Sopenharmony_ci} 139262306a36Sopenharmony_ci 139362306a36Sopenharmony_ci/** 139462306a36Sopenharmony_ci * dwc3_prepare_last_sg - prepare TRBs for the last SG entry 139562306a36Sopenharmony_ci * @dep: The endpoint that the request belongs to 139662306a36Sopenharmony_ci * @req: The request to prepare 139762306a36Sopenharmony_ci * @entry_length: The last SG entry size 139862306a36Sopenharmony_ci * @node: Indicates whether this is not the first entry (for isoc only) 139962306a36Sopenharmony_ci * 140062306a36Sopenharmony_ci * Return the number of TRBs prepared. 140162306a36Sopenharmony_ci */ 140262306a36Sopenharmony_cistatic int dwc3_prepare_last_sg(struct dwc3_ep *dep, 140362306a36Sopenharmony_ci struct dwc3_request *req, unsigned int entry_length, 140462306a36Sopenharmony_ci unsigned int node) 140562306a36Sopenharmony_ci{ 140662306a36Sopenharmony_ci unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc); 140762306a36Sopenharmony_ci unsigned int rem = req->request.length % maxp; 140862306a36Sopenharmony_ci unsigned int num_trbs = 1; 140962306a36Sopenharmony_ci 141062306a36Sopenharmony_ci if (dwc3_needs_extra_trb(dep, req)) 141162306a36Sopenharmony_ci num_trbs++; 141262306a36Sopenharmony_ci 141362306a36Sopenharmony_ci if (dwc3_calc_trbs_left(dep) < num_trbs) 141462306a36Sopenharmony_ci return 0; 141562306a36Sopenharmony_ci 141662306a36Sopenharmony_ci req->needs_extra_trb = num_trbs > 1; 141762306a36Sopenharmony_ci 141862306a36Sopenharmony_ci /* Prepare a normal TRB */ 141962306a36Sopenharmony_ci if (req->direction || req->request.length) 142062306a36Sopenharmony_ci dwc3_prepare_one_trb(dep, req, entry_length, 142162306a36Sopenharmony_ci req->needs_extra_trb, node, false, false); 142262306a36Sopenharmony_ci 142362306a36Sopenharmony_ci /* Prepare extra TRBs for ZLP and MPS OUT transfer alignment */ 142462306a36Sopenharmony_ci if ((!req->direction && !req->request.length) || req->needs_extra_trb) 142562306a36Sopenharmony_ci dwc3_prepare_one_trb(dep, req, 142662306a36Sopenharmony_ci req->direction ? 0 : maxp - rem, 142762306a36Sopenharmony_ci false, 1, true, false); 142862306a36Sopenharmony_ci 142962306a36Sopenharmony_ci return num_trbs; 143062306a36Sopenharmony_ci} 143162306a36Sopenharmony_ci 143262306a36Sopenharmony_cistatic int dwc3_prepare_trbs_sg(struct dwc3_ep *dep, 143362306a36Sopenharmony_ci struct dwc3_request *req) 143462306a36Sopenharmony_ci{ 143562306a36Sopenharmony_ci struct scatterlist *sg = req->start_sg; 143662306a36Sopenharmony_ci struct scatterlist *s; 143762306a36Sopenharmony_ci int i; 143862306a36Sopenharmony_ci unsigned int length = req->request.length; 143962306a36Sopenharmony_ci unsigned int remaining = req->request.num_mapped_sgs 144062306a36Sopenharmony_ci - req->num_queued_sgs; 144162306a36Sopenharmony_ci unsigned int num_trbs = req->num_trbs; 144262306a36Sopenharmony_ci bool needs_extra_trb = dwc3_needs_extra_trb(dep, req); 144362306a36Sopenharmony_ci 144462306a36Sopenharmony_ci /* 144562306a36Sopenharmony_ci * If we resume preparing the request, then get the remaining length of 144662306a36Sopenharmony_ci * the request and resume where we left off. 144762306a36Sopenharmony_ci */ 144862306a36Sopenharmony_ci for_each_sg(req->request.sg, s, req->num_queued_sgs, i) 144962306a36Sopenharmony_ci length -= sg_dma_len(s); 145062306a36Sopenharmony_ci 145162306a36Sopenharmony_ci for_each_sg(sg, s, remaining, i) { 145262306a36Sopenharmony_ci unsigned int num_trbs_left = dwc3_calc_trbs_left(dep); 145362306a36Sopenharmony_ci unsigned int trb_length; 145462306a36Sopenharmony_ci bool must_interrupt = false; 145562306a36Sopenharmony_ci bool last_sg = false; 145662306a36Sopenharmony_ci 145762306a36Sopenharmony_ci trb_length = min_t(unsigned int, length, sg_dma_len(s)); 145862306a36Sopenharmony_ci 145962306a36Sopenharmony_ci length -= trb_length; 146062306a36Sopenharmony_ci 146162306a36Sopenharmony_ci /* 146262306a36Sopenharmony_ci * IOMMU driver is coalescing the list of sgs which shares a 146362306a36Sopenharmony_ci * page boundary into one and giving it to USB driver. With 146462306a36Sopenharmony_ci * this the number of sgs mapped is not equal to the number of 146562306a36Sopenharmony_ci * sgs passed. So mark the chain bit to false if it isthe last 146662306a36Sopenharmony_ci * mapped sg. 146762306a36Sopenharmony_ci */ 146862306a36Sopenharmony_ci if ((i == remaining - 1) || !length) 146962306a36Sopenharmony_ci last_sg = true; 147062306a36Sopenharmony_ci 147162306a36Sopenharmony_ci if (!num_trbs_left) 147262306a36Sopenharmony_ci break; 147362306a36Sopenharmony_ci 147462306a36Sopenharmony_ci if (last_sg) { 147562306a36Sopenharmony_ci if (!dwc3_prepare_last_sg(dep, req, trb_length, i)) 147662306a36Sopenharmony_ci break; 147762306a36Sopenharmony_ci } else { 147862306a36Sopenharmony_ci /* 147962306a36Sopenharmony_ci * Look ahead to check if we have enough TRBs for the 148062306a36Sopenharmony_ci * next SG entry. If not, set interrupt on this TRB to 148162306a36Sopenharmony_ci * resume preparing the next SG entry when more TRBs are 148262306a36Sopenharmony_ci * free. 148362306a36Sopenharmony_ci */ 148462306a36Sopenharmony_ci if (num_trbs_left == 1 || (needs_extra_trb && 148562306a36Sopenharmony_ci num_trbs_left <= 2 && 148662306a36Sopenharmony_ci sg_dma_len(sg_next(s)) >= length)) { 148762306a36Sopenharmony_ci struct dwc3_request *r; 148862306a36Sopenharmony_ci 148962306a36Sopenharmony_ci /* Check if previous requests already set IOC */ 149062306a36Sopenharmony_ci list_for_each_entry(r, &dep->started_list, list) { 149162306a36Sopenharmony_ci if (r != req && !r->request.no_interrupt) 149262306a36Sopenharmony_ci break; 149362306a36Sopenharmony_ci 149462306a36Sopenharmony_ci if (r == req) 149562306a36Sopenharmony_ci must_interrupt = true; 149662306a36Sopenharmony_ci } 149762306a36Sopenharmony_ci } 149862306a36Sopenharmony_ci 149962306a36Sopenharmony_ci dwc3_prepare_one_trb(dep, req, trb_length, 1, i, false, 150062306a36Sopenharmony_ci must_interrupt); 150162306a36Sopenharmony_ci } 150262306a36Sopenharmony_ci 150362306a36Sopenharmony_ci /* 150462306a36Sopenharmony_ci * There can be a situation where all sgs in sglist are not 150562306a36Sopenharmony_ci * queued because of insufficient trb number. To handle this 150662306a36Sopenharmony_ci * case, update start_sg to next sg to be queued, so that 150762306a36Sopenharmony_ci * we have free trbs we can continue queuing from where we 150862306a36Sopenharmony_ci * previously stopped 150962306a36Sopenharmony_ci */ 151062306a36Sopenharmony_ci if (!last_sg) 151162306a36Sopenharmony_ci req->start_sg = sg_next(s); 151262306a36Sopenharmony_ci 151362306a36Sopenharmony_ci req->num_queued_sgs++; 151462306a36Sopenharmony_ci req->num_pending_sgs--; 151562306a36Sopenharmony_ci 151662306a36Sopenharmony_ci /* 151762306a36Sopenharmony_ci * The number of pending SG entries may not correspond to the 151862306a36Sopenharmony_ci * number of mapped SG entries. If all the data are queued, then 151962306a36Sopenharmony_ci * don't include unused SG entries. 152062306a36Sopenharmony_ci */ 152162306a36Sopenharmony_ci if (length == 0) { 152262306a36Sopenharmony_ci req->num_pending_sgs = 0; 152362306a36Sopenharmony_ci break; 152462306a36Sopenharmony_ci } 152562306a36Sopenharmony_ci 152662306a36Sopenharmony_ci if (must_interrupt) 152762306a36Sopenharmony_ci break; 152862306a36Sopenharmony_ci } 152962306a36Sopenharmony_ci 153062306a36Sopenharmony_ci return req->num_trbs - num_trbs; 153162306a36Sopenharmony_ci} 153262306a36Sopenharmony_ci 153362306a36Sopenharmony_cistatic int dwc3_prepare_trbs_linear(struct dwc3_ep *dep, 153462306a36Sopenharmony_ci struct dwc3_request *req) 153562306a36Sopenharmony_ci{ 153662306a36Sopenharmony_ci return dwc3_prepare_last_sg(dep, req, req->request.length, 0); 153762306a36Sopenharmony_ci} 153862306a36Sopenharmony_ci 153962306a36Sopenharmony_ci/* 154062306a36Sopenharmony_ci * dwc3_prepare_trbs - setup TRBs from requests 154162306a36Sopenharmony_ci * @dep: endpoint for which requests are being prepared 154262306a36Sopenharmony_ci * 154362306a36Sopenharmony_ci * The function goes through the requests list and sets up TRBs for the 154462306a36Sopenharmony_ci * transfers. The function returns once there are no more TRBs available or 154562306a36Sopenharmony_ci * it runs out of requests. 154662306a36Sopenharmony_ci * 154762306a36Sopenharmony_ci * Returns the number of TRBs prepared or negative errno. 154862306a36Sopenharmony_ci */ 154962306a36Sopenharmony_cistatic int dwc3_prepare_trbs(struct dwc3_ep *dep) 155062306a36Sopenharmony_ci{ 155162306a36Sopenharmony_ci struct dwc3_request *req, *n; 155262306a36Sopenharmony_ci int ret = 0; 155362306a36Sopenharmony_ci 155462306a36Sopenharmony_ci BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM); 155562306a36Sopenharmony_ci 155662306a36Sopenharmony_ci /* 155762306a36Sopenharmony_ci * We can get in a situation where there's a request in the started list 155862306a36Sopenharmony_ci * but there weren't enough TRBs to fully kick it in the first time 155962306a36Sopenharmony_ci * around, so it has been waiting for more TRBs to be freed up. 156062306a36Sopenharmony_ci * 156162306a36Sopenharmony_ci * In that case, we should check if we have a request with pending_sgs 156262306a36Sopenharmony_ci * in the started list and prepare TRBs for that request first, 156362306a36Sopenharmony_ci * otherwise we will prepare TRBs completely out of order and that will 156462306a36Sopenharmony_ci * break things. 156562306a36Sopenharmony_ci */ 156662306a36Sopenharmony_ci list_for_each_entry(req, &dep->started_list, list) { 156762306a36Sopenharmony_ci if (req->num_pending_sgs > 0) { 156862306a36Sopenharmony_ci ret = dwc3_prepare_trbs_sg(dep, req); 156962306a36Sopenharmony_ci if (!ret || req->num_pending_sgs) 157062306a36Sopenharmony_ci return ret; 157162306a36Sopenharmony_ci } 157262306a36Sopenharmony_ci 157362306a36Sopenharmony_ci if (!dwc3_calc_trbs_left(dep)) 157462306a36Sopenharmony_ci return ret; 157562306a36Sopenharmony_ci 157662306a36Sopenharmony_ci /* 157762306a36Sopenharmony_ci * Don't prepare beyond a transfer. In DWC_usb32, its transfer 157862306a36Sopenharmony_ci * burst capability may try to read and use TRBs beyond the 157962306a36Sopenharmony_ci * active transfer instead of stopping. 158062306a36Sopenharmony_ci */ 158162306a36Sopenharmony_ci if (dep->stream_capable && req->request.is_last && 158262306a36Sopenharmony_ci !DWC3_MST_CAPABLE(&dep->dwc->hwparams)) 158362306a36Sopenharmony_ci return ret; 158462306a36Sopenharmony_ci } 158562306a36Sopenharmony_ci 158662306a36Sopenharmony_ci list_for_each_entry_safe(req, n, &dep->pending_list, list) { 158762306a36Sopenharmony_ci struct dwc3 *dwc = dep->dwc; 158862306a36Sopenharmony_ci 158962306a36Sopenharmony_ci ret = usb_gadget_map_request_by_dev(dwc->sysdev, &req->request, 159062306a36Sopenharmony_ci dep->direction); 159162306a36Sopenharmony_ci if (ret) 159262306a36Sopenharmony_ci return ret; 159362306a36Sopenharmony_ci 159462306a36Sopenharmony_ci req->sg = req->request.sg; 159562306a36Sopenharmony_ci req->start_sg = req->sg; 159662306a36Sopenharmony_ci req->num_queued_sgs = 0; 159762306a36Sopenharmony_ci req->num_pending_sgs = req->request.num_mapped_sgs; 159862306a36Sopenharmony_ci 159962306a36Sopenharmony_ci if (req->num_pending_sgs > 0) { 160062306a36Sopenharmony_ci ret = dwc3_prepare_trbs_sg(dep, req); 160162306a36Sopenharmony_ci if (req->num_pending_sgs) 160262306a36Sopenharmony_ci return ret; 160362306a36Sopenharmony_ci } else { 160462306a36Sopenharmony_ci ret = dwc3_prepare_trbs_linear(dep, req); 160562306a36Sopenharmony_ci } 160662306a36Sopenharmony_ci 160762306a36Sopenharmony_ci if (!ret || !dwc3_calc_trbs_left(dep)) 160862306a36Sopenharmony_ci return ret; 160962306a36Sopenharmony_ci 161062306a36Sopenharmony_ci /* 161162306a36Sopenharmony_ci * Don't prepare beyond a transfer. In DWC_usb32, its transfer 161262306a36Sopenharmony_ci * burst capability may try to read and use TRBs beyond the 161362306a36Sopenharmony_ci * active transfer instead of stopping. 161462306a36Sopenharmony_ci */ 161562306a36Sopenharmony_ci if (dep->stream_capable && req->request.is_last && 161662306a36Sopenharmony_ci !DWC3_MST_CAPABLE(&dwc->hwparams)) 161762306a36Sopenharmony_ci return ret; 161862306a36Sopenharmony_ci } 161962306a36Sopenharmony_ci 162062306a36Sopenharmony_ci return ret; 162162306a36Sopenharmony_ci} 162262306a36Sopenharmony_ci 162362306a36Sopenharmony_cistatic void dwc3_gadget_ep_cleanup_cancelled_requests(struct dwc3_ep *dep); 162462306a36Sopenharmony_ci 162562306a36Sopenharmony_cistatic int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep) 162662306a36Sopenharmony_ci{ 162762306a36Sopenharmony_ci struct dwc3_gadget_ep_cmd_params params; 162862306a36Sopenharmony_ci struct dwc3_request *req; 162962306a36Sopenharmony_ci int starting; 163062306a36Sopenharmony_ci int ret; 163162306a36Sopenharmony_ci u32 cmd; 163262306a36Sopenharmony_ci 163362306a36Sopenharmony_ci /* 163462306a36Sopenharmony_ci * Note that it's normal to have no new TRBs prepared (i.e. ret == 0). 163562306a36Sopenharmony_ci * This happens when we need to stop and restart a transfer such as in 163662306a36Sopenharmony_ci * the case of reinitiating a stream or retrying an isoc transfer. 163762306a36Sopenharmony_ci */ 163862306a36Sopenharmony_ci ret = dwc3_prepare_trbs(dep); 163962306a36Sopenharmony_ci if (ret < 0) 164062306a36Sopenharmony_ci return ret; 164162306a36Sopenharmony_ci 164262306a36Sopenharmony_ci starting = !(dep->flags & DWC3_EP_TRANSFER_STARTED); 164362306a36Sopenharmony_ci 164462306a36Sopenharmony_ci /* 164562306a36Sopenharmony_ci * If there's no new TRB prepared and we don't need to restart a 164662306a36Sopenharmony_ci * transfer, there's no need to update the transfer. 164762306a36Sopenharmony_ci */ 164862306a36Sopenharmony_ci if (!ret && !starting) 164962306a36Sopenharmony_ci return ret; 165062306a36Sopenharmony_ci 165162306a36Sopenharmony_ci req = next_request(&dep->started_list); 165262306a36Sopenharmony_ci if (!req) { 165362306a36Sopenharmony_ci dep->flags |= DWC3_EP_PENDING_REQUEST; 165462306a36Sopenharmony_ci return 0; 165562306a36Sopenharmony_ci } 165662306a36Sopenharmony_ci 165762306a36Sopenharmony_ci memset(¶ms, 0, sizeof(params)); 165862306a36Sopenharmony_ci 165962306a36Sopenharmony_ci if (starting) { 166062306a36Sopenharmony_ci params.param0 = upper_32_bits(req->trb_dma); 166162306a36Sopenharmony_ci params.param1 = lower_32_bits(req->trb_dma); 166262306a36Sopenharmony_ci cmd = DWC3_DEPCMD_STARTTRANSFER; 166362306a36Sopenharmony_ci 166462306a36Sopenharmony_ci if (dep->stream_capable) 166562306a36Sopenharmony_ci cmd |= DWC3_DEPCMD_PARAM(req->request.stream_id); 166662306a36Sopenharmony_ci 166762306a36Sopenharmony_ci if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) 166862306a36Sopenharmony_ci cmd |= DWC3_DEPCMD_PARAM(dep->frame_number); 166962306a36Sopenharmony_ci } else { 167062306a36Sopenharmony_ci cmd = DWC3_DEPCMD_UPDATETRANSFER | 167162306a36Sopenharmony_ci DWC3_DEPCMD_PARAM(dep->resource_index); 167262306a36Sopenharmony_ci } 167362306a36Sopenharmony_ci 167462306a36Sopenharmony_ci ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms); 167562306a36Sopenharmony_ci if (ret < 0) { 167662306a36Sopenharmony_ci struct dwc3_request *tmp; 167762306a36Sopenharmony_ci 167862306a36Sopenharmony_ci if (ret == -EAGAIN) 167962306a36Sopenharmony_ci return ret; 168062306a36Sopenharmony_ci 168162306a36Sopenharmony_ci dwc3_stop_active_transfer(dep, true, true); 168262306a36Sopenharmony_ci 168362306a36Sopenharmony_ci list_for_each_entry_safe(req, tmp, &dep->started_list, list) 168462306a36Sopenharmony_ci dwc3_gadget_move_cancelled_request(req, DWC3_REQUEST_STATUS_DEQUEUED); 168562306a36Sopenharmony_ci 168662306a36Sopenharmony_ci /* If ep isn't started, then there's no end transfer pending */ 168762306a36Sopenharmony_ci if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) 168862306a36Sopenharmony_ci dwc3_gadget_ep_cleanup_cancelled_requests(dep); 168962306a36Sopenharmony_ci 169062306a36Sopenharmony_ci return ret; 169162306a36Sopenharmony_ci } 169262306a36Sopenharmony_ci 169362306a36Sopenharmony_ci if (dep->stream_capable && req->request.is_last && 169462306a36Sopenharmony_ci !DWC3_MST_CAPABLE(&dep->dwc->hwparams)) 169562306a36Sopenharmony_ci dep->flags |= DWC3_EP_WAIT_TRANSFER_COMPLETE; 169662306a36Sopenharmony_ci 169762306a36Sopenharmony_ci return 0; 169862306a36Sopenharmony_ci} 169962306a36Sopenharmony_ci 170062306a36Sopenharmony_cistatic int __dwc3_gadget_get_frame(struct dwc3 *dwc) 170162306a36Sopenharmony_ci{ 170262306a36Sopenharmony_ci u32 reg; 170362306a36Sopenharmony_ci 170462306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_DSTS); 170562306a36Sopenharmony_ci return DWC3_DSTS_SOFFN(reg); 170662306a36Sopenharmony_ci} 170762306a36Sopenharmony_ci 170862306a36Sopenharmony_ci/** 170962306a36Sopenharmony_ci * __dwc3_stop_active_transfer - stop the current active transfer 171062306a36Sopenharmony_ci * @dep: isoc endpoint 171162306a36Sopenharmony_ci * @force: set forcerm bit in the command 171262306a36Sopenharmony_ci * @interrupt: command complete interrupt after End Transfer command 171362306a36Sopenharmony_ci * 171462306a36Sopenharmony_ci * When setting force, the ForceRM bit will be set. In that case 171562306a36Sopenharmony_ci * the controller won't update the TRB progress on command 171662306a36Sopenharmony_ci * completion. It also won't clear the HWO bit in the TRB. 171762306a36Sopenharmony_ci * The command will also not complete immediately in that case. 171862306a36Sopenharmony_ci */ 171962306a36Sopenharmony_cistatic int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool interrupt) 172062306a36Sopenharmony_ci{ 172162306a36Sopenharmony_ci struct dwc3 *dwc = dep->dwc; 172262306a36Sopenharmony_ci struct dwc3_gadget_ep_cmd_params params; 172362306a36Sopenharmony_ci u32 cmd; 172462306a36Sopenharmony_ci int ret; 172562306a36Sopenharmony_ci 172662306a36Sopenharmony_ci cmd = DWC3_DEPCMD_ENDTRANSFER; 172762306a36Sopenharmony_ci cmd |= force ? DWC3_DEPCMD_HIPRI_FORCERM : 0; 172862306a36Sopenharmony_ci cmd |= interrupt ? DWC3_DEPCMD_CMDIOC : 0; 172962306a36Sopenharmony_ci cmd |= DWC3_DEPCMD_PARAM(dep->resource_index); 173062306a36Sopenharmony_ci memset(¶ms, 0, sizeof(params)); 173162306a36Sopenharmony_ci ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms); 173262306a36Sopenharmony_ci /* 173362306a36Sopenharmony_ci * If the End Transfer command was timed out while the device is 173462306a36Sopenharmony_ci * not in SETUP phase, it's possible that an incoming Setup packet 173562306a36Sopenharmony_ci * may prevent the command's completion. Let's retry when the 173662306a36Sopenharmony_ci * ep0state returns to EP0_SETUP_PHASE. 173762306a36Sopenharmony_ci */ 173862306a36Sopenharmony_ci if (ret == -ETIMEDOUT && dep->dwc->ep0state != EP0_SETUP_PHASE) { 173962306a36Sopenharmony_ci dep->flags |= DWC3_EP_DELAY_STOP; 174062306a36Sopenharmony_ci return 0; 174162306a36Sopenharmony_ci } 174262306a36Sopenharmony_ci WARN_ON_ONCE(ret); 174362306a36Sopenharmony_ci dep->resource_index = 0; 174462306a36Sopenharmony_ci 174562306a36Sopenharmony_ci if (!interrupt) { 174662306a36Sopenharmony_ci if (!DWC3_IP_IS(DWC3) || DWC3_VER_IS_PRIOR(DWC3, 310A)) 174762306a36Sopenharmony_ci mdelay(1); 174862306a36Sopenharmony_ci dep->flags &= ~DWC3_EP_TRANSFER_STARTED; 174962306a36Sopenharmony_ci } else if (!ret) { 175062306a36Sopenharmony_ci dep->flags |= DWC3_EP_END_TRANSFER_PENDING; 175162306a36Sopenharmony_ci } 175262306a36Sopenharmony_ci 175362306a36Sopenharmony_ci dep->flags &= ~DWC3_EP_DELAY_STOP; 175462306a36Sopenharmony_ci return ret; 175562306a36Sopenharmony_ci} 175662306a36Sopenharmony_ci 175762306a36Sopenharmony_ci/** 175862306a36Sopenharmony_ci * dwc3_gadget_start_isoc_quirk - workaround invalid frame number 175962306a36Sopenharmony_ci * @dep: isoc endpoint 176062306a36Sopenharmony_ci * 176162306a36Sopenharmony_ci * This function tests for the correct combination of BIT[15:14] from the 16-bit 176262306a36Sopenharmony_ci * microframe number reported by the XferNotReady event for the future frame 176362306a36Sopenharmony_ci * number to start the isoc transfer. 176462306a36Sopenharmony_ci * 176562306a36Sopenharmony_ci * In DWC_usb31 version 1.70a-ea06 and prior, for highspeed and fullspeed 176662306a36Sopenharmony_ci * isochronous IN, BIT[15:14] of the 16-bit microframe number reported by the 176762306a36Sopenharmony_ci * XferNotReady event are invalid. The driver uses this number to schedule the 176862306a36Sopenharmony_ci * isochronous transfer and passes it to the START TRANSFER command. Because 176962306a36Sopenharmony_ci * this number is invalid, the command may fail. If BIT[15:14] matches the 177062306a36Sopenharmony_ci * internal 16-bit microframe, the START TRANSFER command will pass and the 177162306a36Sopenharmony_ci * transfer will start at the scheduled time, if it is off by 1, the command 177262306a36Sopenharmony_ci * will still pass, but the transfer will start 2 seconds in the future. For all 177362306a36Sopenharmony_ci * other conditions, the START TRANSFER command will fail with bus-expiry. 177462306a36Sopenharmony_ci * 177562306a36Sopenharmony_ci * In order to workaround this issue, we can test for the correct combination of 177662306a36Sopenharmony_ci * BIT[15:14] by sending START TRANSFER commands with different values of 177762306a36Sopenharmony_ci * BIT[15:14]: 'b00, 'b01, 'b10, and 'b11. Each combination is 2^14 uframe apart 177862306a36Sopenharmony_ci * (or 2 seconds). 4 seconds into the future will result in a bus-expiry status. 177962306a36Sopenharmony_ci * As the result, within the 4 possible combinations for BIT[15:14], there will 178062306a36Sopenharmony_ci * be 2 successful and 2 failure START COMMAND status. One of the 2 successful 178162306a36Sopenharmony_ci * command status will result in a 2-second delay start. The smaller BIT[15:14] 178262306a36Sopenharmony_ci * value is the correct combination. 178362306a36Sopenharmony_ci * 178462306a36Sopenharmony_ci * Since there are only 4 outcomes and the results are ordered, we can simply 178562306a36Sopenharmony_ci * test 2 START TRANSFER commands with BIT[15:14] combinations 'b00 and 'b01 to 178662306a36Sopenharmony_ci * deduce the smaller successful combination. 178762306a36Sopenharmony_ci * 178862306a36Sopenharmony_ci * Let test0 = test status for combination 'b00 and test1 = test status for 'b01 178962306a36Sopenharmony_ci * of BIT[15:14]. The correct combination is as follow: 179062306a36Sopenharmony_ci * 179162306a36Sopenharmony_ci * if test0 fails and test1 passes, BIT[15:14] is 'b01 179262306a36Sopenharmony_ci * if test0 fails and test1 fails, BIT[15:14] is 'b10 179362306a36Sopenharmony_ci * if test0 passes and test1 fails, BIT[15:14] is 'b11 179462306a36Sopenharmony_ci * if test0 passes and test1 passes, BIT[15:14] is 'b00 179562306a36Sopenharmony_ci * 179662306a36Sopenharmony_ci * Synopsys STAR 9001202023: Wrong microframe number for isochronous IN 179762306a36Sopenharmony_ci * endpoints. 179862306a36Sopenharmony_ci */ 179962306a36Sopenharmony_cistatic int dwc3_gadget_start_isoc_quirk(struct dwc3_ep *dep) 180062306a36Sopenharmony_ci{ 180162306a36Sopenharmony_ci int cmd_status = 0; 180262306a36Sopenharmony_ci bool test0; 180362306a36Sopenharmony_ci bool test1; 180462306a36Sopenharmony_ci 180562306a36Sopenharmony_ci while (dep->combo_num < 2) { 180662306a36Sopenharmony_ci struct dwc3_gadget_ep_cmd_params params; 180762306a36Sopenharmony_ci u32 test_frame_number; 180862306a36Sopenharmony_ci u32 cmd; 180962306a36Sopenharmony_ci 181062306a36Sopenharmony_ci /* 181162306a36Sopenharmony_ci * Check if we can start isoc transfer on the next interval or 181262306a36Sopenharmony_ci * 4 uframes in the future with BIT[15:14] as dep->combo_num 181362306a36Sopenharmony_ci */ 181462306a36Sopenharmony_ci test_frame_number = dep->frame_number & DWC3_FRNUMBER_MASK; 181562306a36Sopenharmony_ci test_frame_number |= dep->combo_num << 14; 181662306a36Sopenharmony_ci test_frame_number += max_t(u32, 4, dep->interval); 181762306a36Sopenharmony_ci 181862306a36Sopenharmony_ci params.param0 = upper_32_bits(dep->dwc->bounce_addr); 181962306a36Sopenharmony_ci params.param1 = lower_32_bits(dep->dwc->bounce_addr); 182062306a36Sopenharmony_ci 182162306a36Sopenharmony_ci cmd = DWC3_DEPCMD_STARTTRANSFER; 182262306a36Sopenharmony_ci cmd |= DWC3_DEPCMD_PARAM(test_frame_number); 182362306a36Sopenharmony_ci cmd_status = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms); 182462306a36Sopenharmony_ci 182562306a36Sopenharmony_ci /* Redo if some other failure beside bus-expiry is received */ 182662306a36Sopenharmony_ci if (cmd_status && cmd_status != -EAGAIN) { 182762306a36Sopenharmony_ci dep->start_cmd_status = 0; 182862306a36Sopenharmony_ci dep->combo_num = 0; 182962306a36Sopenharmony_ci return 0; 183062306a36Sopenharmony_ci } 183162306a36Sopenharmony_ci 183262306a36Sopenharmony_ci /* Store the first test status */ 183362306a36Sopenharmony_ci if (dep->combo_num == 0) 183462306a36Sopenharmony_ci dep->start_cmd_status = cmd_status; 183562306a36Sopenharmony_ci 183662306a36Sopenharmony_ci dep->combo_num++; 183762306a36Sopenharmony_ci 183862306a36Sopenharmony_ci /* 183962306a36Sopenharmony_ci * End the transfer if the START_TRANSFER command is successful 184062306a36Sopenharmony_ci * to wait for the next XferNotReady to test the command again 184162306a36Sopenharmony_ci */ 184262306a36Sopenharmony_ci if (cmd_status == 0) { 184362306a36Sopenharmony_ci dwc3_stop_active_transfer(dep, true, true); 184462306a36Sopenharmony_ci return 0; 184562306a36Sopenharmony_ci } 184662306a36Sopenharmony_ci } 184762306a36Sopenharmony_ci 184862306a36Sopenharmony_ci /* test0 and test1 are both completed at this point */ 184962306a36Sopenharmony_ci test0 = (dep->start_cmd_status == 0); 185062306a36Sopenharmony_ci test1 = (cmd_status == 0); 185162306a36Sopenharmony_ci 185262306a36Sopenharmony_ci if (!test0 && test1) 185362306a36Sopenharmony_ci dep->combo_num = 1; 185462306a36Sopenharmony_ci else if (!test0 && !test1) 185562306a36Sopenharmony_ci dep->combo_num = 2; 185662306a36Sopenharmony_ci else if (test0 && !test1) 185762306a36Sopenharmony_ci dep->combo_num = 3; 185862306a36Sopenharmony_ci else if (test0 && test1) 185962306a36Sopenharmony_ci dep->combo_num = 0; 186062306a36Sopenharmony_ci 186162306a36Sopenharmony_ci dep->frame_number &= DWC3_FRNUMBER_MASK; 186262306a36Sopenharmony_ci dep->frame_number |= dep->combo_num << 14; 186362306a36Sopenharmony_ci dep->frame_number += max_t(u32, 4, dep->interval); 186462306a36Sopenharmony_ci 186562306a36Sopenharmony_ci /* Reinitialize test variables */ 186662306a36Sopenharmony_ci dep->start_cmd_status = 0; 186762306a36Sopenharmony_ci dep->combo_num = 0; 186862306a36Sopenharmony_ci 186962306a36Sopenharmony_ci return __dwc3_gadget_kick_transfer(dep); 187062306a36Sopenharmony_ci} 187162306a36Sopenharmony_ci 187262306a36Sopenharmony_cistatic int __dwc3_gadget_start_isoc(struct dwc3_ep *dep) 187362306a36Sopenharmony_ci{ 187462306a36Sopenharmony_ci const struct usb_endpoint_descriptor *desc = dep->endpoint.desc; 187562306a36Sopenharmony_ci struct dwc3 *dwc = dep->dwc; 187662306a36Sopenharmony_ci int ret; 187762306a36Sopenharmony_ci int i; 187862306a36Sopenharmony_ci 187962306a36Sopenharmony_ci if (list_empty(&dep->pending_list) && 188062306a36Sopenharmony_ci list_empty(&dep->started_list)) { 188162306a36Sopenharmony_ci dep->flags |= DWC3_EP_PENDING_REQUEST; 188262306a36Sopenharmony_ci return -EAGAIN; 188362306a36Sopenharmony_ci } 188462306a36Sopenharmony_ci 188562306a36Sopenharmony_ci if (!dwc->dis_start_transfer_quirk && 188662306a36Sopenharmony_ci (DWC3_VER_IS_PRIOR(DWC31, 170A) || 188762306a36Sopenharmony_ci DWC3_VER_TYPE_IS_WITHIN(DWC31, 170A, EA01, EA06))) { 188862306a36Sopenharmony_ci if (dwc->gadget->speed <= USB_SPEED_HIGH && dep->direction) 188962306a36Sopenharmony_ci return dwc3_gadget_start_isoc_quirk(dep); 189062306a36Sopenharmony_ci } 189162306a36Sopenharmony_ci 189262306a36Sopenharmony_ci if (desc->bInterval <= 14 && 189362306a36Sopenharmony_ci dwc->gadget->speed >= USB_SPEED_HIGH) { 189462306a36Sopenharmony_ci u32 frame = __dwc3_gadget_get_frame(dwc); 189562306a36Sopenharmony_ci bool rollover = frame < 189662306a36Sopenharmony_ci (dep->frame_number & DWC3_FRNUMBER_MASK); 189762306a36Sopenharmony_ci 189862306a36Sopenharmony_ci /* 189962306a36Sopenharmony_ci * frame_number is set from XferNotReady and may be already 190062306a36Sopenharmony_ci * out of date. DSTS only provides the lower 14 bit of the 190162306a36Sopenharmony_ci * current frame number. So add the upper two bits of 190262306a36Sopenharmony_ci * frame_number and handle a possible rollover. 190362306a36Sopenharmony_ci * This will provide the correct frame_number unless more than 190462306a36Sopenharmony_ci * rollover has happened since XferNotReady. 190562306a36Sopenharmony_ci */ 190662306a36Sopenharmony_ci 190762306a36Sopenharmony_ci dep->frame_number = (dep->frame_number & ~DWC3_FRNUMBER_MASK) | 190862306a36Sopenharmony_ci frame; 190962306a36Sopenharmony_ci if (rollover) 191062306a36Sopenharmony_ci dep->frame_number += BIT(14); 191162306a36Sopenharmony_ci } 191262306a36Sopenharmony_ci 191362306a36Sopenharmony_ci for (i = 0; i < DWC3_ISOC_MAX_RETRIES; i++) { 191462306a36Sopenharmony_ci int future_interval = i + 1; 191562306a36Sopenharmony_ci 191662306a36Sopenharmony_ci /* Give the controller at least 500us to schedule transfers */ 191762306a36Sopenharmony_ci if (desc->bInterval < 3) 191862306a36Sopenharmony_ci future_interval += 3 - desc->bInterval; 191962306a36Sopenharmony_ci 192062306a36Sopenharmony_ci dep->frame_number = DWC3_ALIGN_FRAME(dep, future_interval); 192162306a36Sopenharmony_ci 192262306a36Sopenharmony_ci ret = __dwc3_gadget_kick_transfer(dep); 192362306a36Sopenharmony_ci if (ret != -EAGAIN) 192462306a36Sopenharmony_ci break; 192562306a36Sopenharmony_ci } 192662306a36Sopenharmony_ci 192762306a36Sopenharmony_ci /* 192862306a36Sopenharmony_ci * After a number of unsuccessful start attempts due to bus-expiry 192962306a36Sopenharmony_ci * status, issue END_TRANSFER command and retry on the next XferNotReady 193062306a36Sopenharmony_ci * event. 193162306a36Sopenharmony_ci */ 193262306a36Sopenharmony_ci if (ret == -EAGAIN) 193362306a36Sopenharmony_ci ret = __dwc3_stop_active_transfer(dep, false, true); 193462306a36Sopenharmony_ci 193562306a36Sopenharmony_ci return ret; 193662306a36Sopenharmony_ci} 193762306a36Sopenharmony_ci 193862306a36Sopenharmony_cistatic int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) 193962306a36Sopenharmony_ci{ 194062306a36Sopenharmony_ci struct dwc3 *dwc = dep->dwc; 194162306a36Sopenharmony_ci 194262306a36Sopenharmony_ci if (!dep->endpoint.desc || !dwc->pullups_connected || !dwc->connected) { 194362306a36Sopenharmony_ci dev_dbg(dwc->dev, "%s: can't queue to disabled endpoint\n", 194462306a36Sopenharmony_ci dep->name); 194562306a36Sopenharmony_ci return -ESHUTDOWN; 194662306a36Sopenharmony_ci } 194762306a36Sopenharmony_ci 194862306a36Sopenharmony_ci if (WARN(req->dep != dep, "request %pK belongs to '%s'\n", 194962306a36Sopenharmony_ci &req->request, req->dep->name)) 195062306a36Sopenharmony_ci return -EINVAL; 195162306a36Sopenharmony_ci 195262306a36Sopenharmony_ci if (WARN(req->status < DWC3_REQUEST_STATUS_COMPLETED, 195362306a36Sopenharmony_ci "%s: request %pK already in flight\n", 195462306a36Sopenharmony_ci dep->name, &req->request)) 195562306a36Sopenharmony_ci return -EINVAL; 195662306a36Sopenharmony_ci 195762306a36Sopenharmony_ci pm_runtime_get(dwc->dev); 195862306a36Sopenharmony_ci 195962306a36Sopenharmony_ci req->request.actual = 0; 196062306a36Sopenharmony_ci req->request.status = -EINPROGRESS; 196162306a36Sopenharmony_ci 196262306a36Sopenharmony_ci trace_dwc3_ep_queue(req); 196362306a36Sopenharmony_ci 196462306a36Sopenharmony_ci list_add_tail(&req->list, &dep->pending_list); 196562306a36Sopenharmony_ci req->status = DWC3_REQUEST_STATUS_QUEUED; 196662306a36Sopenharmony_ci 196762306a36Sopenharmony_ci if (dep->flags & DWC3_EP_WAIT_TRANSFER_COMPLETE) 196862306a36Sopenharmony_ci return 0; 196962306a36Sopenharmony_ci 197062306a36Sopenharmony_ci /* 197162306a36Sopenharmony_ci * Start the transfer only after the END_TRANSFER is completed 197262306a36Sopenharmony_ci * and endpoint STALL is cleared. 197362306a36Sopenharmony_ci */ 197462306a36Sopenharmony_ci if ((dep->flags & DWC3_EP_END_TRANSFER_PENDING) || 197562306a36Sopenharmony_ci (dep->flags & DWC3_EP_WEDGE) || 197662306a36Sopenharmony_ci (dep->flags & DWC3_EP_DELAY_STOP) || 197762306a36Sopenharmony_ci (dep->flags & DWC3_EP_STALL)) { 197862306a36Sopenharmony_ci dep->flags |= DWC3_EP_DELAY_START; 197962306a36Sopenharmony_ci return 0; 198062306a36Sopenharmony_ci } 198162306a36Sopenharmony_ci 198262306a36Sopenharmony_ci /* 198362306a36Sopenharmony_ci * NOTICE: Isochronous endpoints should NEVER be prestarted. We must 198462306a36Sopenharmony_ci * wait for a XferNotReady event so we will know what's the current 198562306a36Sopenharmony_ci * (micro-)frame number. 198662306a36Sopenharmony_ci * 198762306a36Sopenharmony_ci * Without this trick, we are very, very likely gonna get Bus Expiry 198862306a36Sopenharmony_ci * errors which will force us issue EndTransfer command. 198962306a36Sopenharmony_ci */ 199062306a36Sopenharmony_ci if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { 199162306a36Sopenharmony_ci if (!(dep->flags & DWC3_EP_TRANSFER_STARTED)) { 199262306a36Sopenharmony_ci if ((dep->flags & DWC3_EP_PENDING_REQUEST)) 199362306a36Sopenharmony_ci return __dwc3_gadget_start_isoc(dep); 199462306a36Sopenharmony_ci 199562306a36Sopenharmony_ci return 0; 199662306a36Sopenharmony_ci } 199762306a36Sopenharmony_ci } 199862306a36Sopenharmony_ci 199962306a36Sopenharmony_ci __dwc3_gadget_kick_transfer(dep); 200062306a36Sopenharmony_ci 200162306a36Sopenharmony_ci return 0; 200262306a36Sopenharmony_ci} 200362306a36Sopenharmony_ci 200462306a36Sopenharmony_cistatic int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request, 200562306a36Sopenharmony_ci gfp_t gfp_flags) 200662306a36Sopenharmony_ci{ 200762306a36Sopenharmony_ci struct dwc3_request *req = to_dwc3_request(request); 200862306a36Sopenharmony_ci struct dwc3_ep *dep = to_dwc3_ep(ep); 200962306a36Sopenharmony_ci struct dwc3 *dwc = dep->dwc; 201062306a36Sopenharmony_ci 201162306a36Sopenharmony_ci unsigned long flags; 201262306a36Sopenharmony_ci 201362306a36Sopenharmony_ci int ret; 201462306a36Sopenharmony_ci 201562306a36Sopenharmony_ci spin_lock_irqsave(&dwc->lock, flags); 201662306a36Sopenharmony_ci ret = __dwc3_gadget_ep_queue(dep, req); 201762306a36Sopenharmony_ci spin_unlock_irqrestore(&dwc->lock, flags); 201862306a36Sopenharmony_ci 201962306a36Sopenharmony_ci return ret; 202062306a36Sopenharmony_ci} 202162306a36Sopenharmony_ci 202262306a36Sopenharmony_cistatic void dwc3_gadget_ep_skip_trbs(struct dwc3_ep *dep, struct dwc3_request *req) 202362306a36Sopenharmony_ci{ 202462306a36Sopenharmony_ci int i; 202562306a36Sopenharmony_ci 202662306a36Sopenharmony_ci /* If req->trb is not set, then the request has not started */ 202762306a36Sopenharmony_ci if (!req->trb) 202862306a36Sopenharmony_ci return; 202962306a36Sopenharmony_ci 203062306a36Sopenharmony_ci /* 203162306a36Sopenharmony_ci * If request was already started, this means we had to 203262306a36Sopenharmony_ci * stop the transfer. With that we also need to ignore 203362306a36Sopenharmony_ci * all TRBs used by the request, however TRBs can only 203462306a36Sopenharmony_ci * be modified after completion of END_TRANSFER 203562306a36Sopenharmony_ci * command. So what we do here is that we wait for 203662306a36Sopenharmony_ci * END_TRANSFER completion and only after that, we jump 203762306a36Sopenharmony_ci * over TRBs by clearing HWO and incrementing dequeue 203862306a36Sopenharmony_ci * pointer. 203962306a36Sopenharmony_ci */ 204062306a36Sopenharmony_ci for (i = 0; i < req->num_trbs; i++) { 204162306a36Sopenharmony_ci struct dwc3_trb *trb; 204262306a36Sopenharmony_ci 204362306a36Sopenharmony_ci trb = &dep->trb_pool[dep->trb_dequeue]; 204462306a36Sopenharmony_ci trb->ctrl &= ~DWC3_TRB_CTRL_HWO; 204562306a36Sopenharmony_ci dwc3_ep_inc_deq(dep); 204662306a36Sopenharmony_ci } 204762306a36Sopenharmony_ci 204862306a36Sopenharmony_ci req->num_trbs = 0; 204962306a36Sopenharmony_ci} 205062306a36Sopenharmony_ci 205162306a36Sopenharmony_cistatic void dwc3_gadget_ep_cleanup_cancelled_requests(struct dwc3_ep *dep) 205262306a36Sopenharmony_ci{ 205362306a36Sopenharmony_ci struct dwc3_request *req; 205462306a36Sopenharmony_ci struct dwc3 *dwc = dep->dwc; 205562306a36Sopenharmony_ci 205662306a36Sopenharmony_ci while (!list_empty(&dep->cancelled_list)) { 205762306a36Sopenharmony_ci req = next_request(&dep->cancelled_list); 205862306a36Sopenharmony_ci dwc3_gadget_ep_skip_trbs(dep, req); 205962306a36Sopenharmony_ci switch (req->status) { 206062306a36Sopenharmony_ci case DWC3_REQUEST_STATUS_DISCONNECTED: 206162306a36Sopenharmony_ci dwc3_gadget_giveback(dep, req, -ESHUTDOWN); 206262306a36Sopenharmony_ci break; 206362306a36Sopenharmony_ci case DWC3_REQUEST_STATUS_DEQUEUED: 206462306a36Sopenharmony_ci dwc3_gadget_giveback(dep, req, -ECONNRESET); 206562306a36Sopenharmony_ci break; 206662306a36Sopenharmony_ci case DWC3_REQUEST_STATUS_STALLED: 206762306a36Sopenharmony_ci dwc3_gadget_giveback(dep, req, -EPIPE); 206862306a36Sopenharmony_ci break; 206962306a36Sopenharmony_ci default: 207062306a36Sopenharmony_ci dev_err(dwc->dev, "request cancelled with wrong reason:%d\n", req->status); 207162306a36Sopenharmony_ci dwc3_gadget_giveback(dep, req, -ECONNRESET); 207262306a36Sopenharmony_ci break; 207362306a36Sopenharmony_ci } 207462306a36Sopenharmony_ci /* 207562306a36Sopenharmony_ci * The endpoint is disabled, let the dwc3_remove_requests() 207662306a36Sopenharmony_ci * handle the cleanup. 207762306a36Sopenharmony_ci */ 207862306a36Sopenharmony_ci if (!dep->endpoint.desc) 207962306a36Sopenharmony_ci break; 208062306a36Sopenharmony_ci } 208162306a36Sopenharmony_ci} 208262306a36Sopenharmony_ci 208362306a36Sopenharmony_cistatic int dwc3_gadget_ep_dequeue(struct usb_ep *ep, 208462306a36Sopenharmony_ci struct usb_request *request) 208562306a36Sopenharmony_ci{ 208662306a36Sopenharmony_ci struct dwc3_request *req = to_dwc3_request(request); 208762306a36Sopenharmony_ci struct dwc3_request *r = NULL; 208862306a36Sopenharmony_ci 208962306a36Sopenharmony_ci struct dwc3_ep *dep = to_dwc3_ep(ep); 209062306a36Sopenharmony_ci struct dwc3 *dwc = dep->dwc; 209162306a36Sopenharmony_ci 209262306a36Sopenharmony_ci unsigned long flags; 209362306a36Sopenharmony_ci int ret = 0; 209462306a36Sopenharmony_ci 209562306a36Sopenharmony_ci trace_dwc3_ep_dequeue(req); 209662306a36Sopenharmony_ci 209762306a36Sopenharmony_ci spin_lock_irqsave(&dwc->lock, flags); 209862306a36Sopenharmony_ci 209962306a36Sopenharmony_ci list_for_each_entry(r, &dep->cancelled_list, list) { 210062306a36Sopenharmony_ci if (r == req) 210162306a36Sopenharmony_ci goto out; 210262306a36Sopenharmony_ci } 210362306a36Sopenharmony_ci 210462306a36Sopenharmony_ci list_for_each_entry(r, &dep->pending_list, list) { 210562306a36Sopenharmony_ci if (r == req) { 210662306a36Sopenharmony_ci /* 210762306a36Sopenharmony_ci * Explicitly check for EP0/1 as dequeue for those 210862306a36Sopenharmony_ci * EPs need to be handled differently. Control EP 210962306a36Sopenharmony_ci * only deals with one USB req, and giveback will 211062306a36Sopenharmony_ci * occur during dwc3_ep0_stall_and_restart(). EP0 211162306a36Sopenharmony_ci * requests are never added to started_list. 211262306a36Sopenharmony_ci */ 211362306a36Sopenharmony_ci if (dep->number > 1) 211462306a36Sopenharmony_ci dwc3_gadget_giveback(dep, req, -ECONNRESET); 211562306a36Sopenharmony_ci else 211662306a36Sopenharmony_ci dwc3_ep0_reset_state(dwc); 211762306a36Sopenharmony_ci goto out; 211862306a36Sopenharmony_ci } 211962306a36Sopenharmony_ci } 212062306a36Sopenharmony_ci 212162306a36Sopenharmony_ci list_for_each_entry(r, &dep->started_list, list) { 212262306a36Sopenharmony_ci if (r == req) { 212362306a36Sopenharmony_ci struct dwc3_request *t; 212462306a36Sopenharmony_ci 212562306a36Sopenharmony_ci /* wait until it is processed */ 212662306a36Sopenharmony_ci dwc3_stop_active_transfer(dep, true, true); 212762306a36Sopenharmony_ci 212862306a36Sopenharmony_ci /* 212962306a36Sopenharmony_ci * Remove any started request if the transfer is 213062306a36Sopenharmony_ci * cancelled. 213162306a36Sopenharmony_ci */ 213262306a36Sopenharmony_ci list_for_each_entry_safe(r, t, &dep->started_list, list) 213362306a36Sopenharmony_ci dwc3_gadget_move_cancelled_request(r, 213462306a36Sopenharmony_ci DWC3_REQUEST_STATUS_DEQUEUED); 213562306a36Sopenharmony_ci 213662306a36Sopenharmony_ci dep->flags &= ~DWC3_EP_WAIT_TRANSFER_COMPLETE; 213762306a36Sopenharmony_ci 213862306a36Sopenharmony_ci goto out; 213962306a36Sopenharmony_ci } 214062306a36Sopenharmony_ci } 214162306a36Sopenharmony_ci 214262306a36Sopenharmony_ci dev_err(dwc->dev, "request %pK was not queued to %s\n", 214362306a36Sopenharmony_ci request, ep->name); 214462306a36Sopenharmony_ci ret = -EINVAL; 214562306a36Sopenharmony_ciout: 214662306a36Sopenharmony_ci spin_unlock_irqrestore(&dwc->lock, flags); 214762306a36Sopenharmony_ci 214862306a36Sopenharmony_ci return ret; 214962306a36Sopenharmony_ci} 215062306a36Sopenharmony_ci 215162306a36Sopenharmony_ciint __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol) 215262306a36Sopenharmony_ci{ 215362306a36Sopenharmony_ci struct dwc3_gadget_ep_cmd_params params; 215462306a36Sopenharmony_ci struct dwc3 *dwc = dep->dwc; 215562306a36Sopenharmony_ci struct dwc3_request *req; 215662306a36Sopenharmony_ci struct dwc3_request *tmp; 215762306a36Sopenharmony_ci int ret; 215862306a36Sopenharmony_ci 215962306a36Sopenharmony_ci if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { 216062306a36Sopenharmony_ci dev_err(dwc->dev, "%s is of Isochronous type\n", dep->name); 216162306a36Sopenharmony_ci return -EINVAL; 216262306a36Sopenharmony_ci } 216362306a36Sopenharmony_ci 216462306a36Sopenharmony_ci memset(¶ms, 0x00, sizeof(params)); 216562306a36Sopenharmony_ci 216662306a36Sopenharmony_ci if (value) { 216762306a36Sopenharmony_ci struct dwc3_trb *trb; 216862306a36Sopenharmony_ci 216962306a36Sopenharmony_ci unsigned int transfer_in_flight; 217062306a36Sopenharmony_ci unsigned int started; 217162306a36Sopenharmony_ci 217262306a36Sopenharmony_ci if (dep->number > 1) 217362306a36Sopenharmony_ci trb = dwc3_ep_prev_trb(dep, dep->trb_enqueue); 217462306a36Sopenharmony_ci else 217562306a36Sopenharmony_ci trb = &dwc->ep0_trb[dep->trb_enqueue]; 217662306a36Sopenharmony_ci 217762306a36Sopenharmony_ci transfer_in_flight = trb->ctrl & DWC3_TRB_CTRL_HWO; 217862306a36Sopenharmony_ci started = !list_empty(&dep->started_list); 217962306a36Sopenharmony_ci 218062306a36Sopenharmony_ci if (!protocol && ((dep->direction && transfer_in_flight) || 218162306a36Sopenharmony_ci (!dep->direction && started))) { 218262306a36Sopenharmony_ci return -EAGAIN; 218362306a36Sopenharmony_ci } 218462306a36Sopenharmony_ci 218562306a36Sopenharmony_ci ret = dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_SETSTALL, 218662306a36Sopenharmony_ci ¶ms); 218762306a36Sopenharmony_ci if (ret) 218862306a36Sopenharmony_ci dev_err(dwc->dev, "failed to set STALL on %s\n", 218962306a36Sopenharmony_ci dep->name); 219062306a36Sopenharmony_ci else 219162306a36Sopenharmony_ci dep->flags |= DWC3_EP_STALL; 219262306a36Sopenharmony_ci } else { 219362306a36Sopenharmony_ci /* 219462306a36Sopenharmony_ci * Don't issue CLEAR_STALL command to control endpoints. The 219562306a36Sopenharmony_ci * controller automatically clears the STALL when it receives 219662306a36Sopenharmony_ci * the SETUP token. 219762306a36Sopenharmony_ci */ 219862306a36Sopenharmony_ci if (dep->number <= 1) { 219962306a36Sopenharmony_ci dep->flags &= ~(DWC3_EP_STALL | DWC3_EP_WEDGE); 220062306a36Sopenharmony_ci return 0; 220162306a36Sopenharmony_ci } 220262306a36Sopenharmony_ci 220362306a36Sopenharmony_ci dwc3_stop_active_transfer(dep, true, true); 220462306a36Sopenharmony_ci 220562306a36Sopenharmony_ci list_for_each_entry_safe(req, tmp, &dep->started_list, list) 220662306a36Sopenharmony_ci dwc3_gadget_move_cancelled_request(req, DWC3_REQUEST_STATUS_STALLED); 220762306a36Sopenharmony_ci 220862306a36Sopenharmony_ci if (dep->flags & DWC3_EP_END_TRANSFER_PENDING || 220962306a36Sopenharmony_ci (dep->flags & DWC3_EP_DELAY_STOP)) { 221062306a36Sopenharmony_ci dep->flags |= DWC3_EP_PENDING_CLEAR_STALL; 221162306a36Sopenharmony_ci if (protocol) 221262306a36Sopenharmony_ci dwc->clear_stall_protocol = dep->number; 221362306a36Sopenharmony_ci 221462306a36Sopenharmony_ci return 0; 221562306a36Sopenharmony_ci } 221662306a36Sopenharmony_ci 221762306a36Sopenharmony_ci dwc3_gadget_ep_cleanup_cancelled_requests(dep); 221862306a36Sopenharmony_ci 221962306a36Sopenharmony_ci ret = dwc3_send_clear_stall_ep_cmd(dep); 222062306a36Sopenharmony_ci if (ret) { 222162306a36Sopenharmony_ci dev_err(dwc->dev, "failed to clear STALL on %s\n", 222262306a36Sopenharmony_ci dep->name); 222362306a36Sopenharmony_ci return ret; 222462306a36Sopenharmony_ci } 222562306a36Sopenharmony_ci 222662306a36Sopenharmony_ci dep->flags &= ~(DWC3_EP_STALL | DWC3_EP_WEDGE); 222762306a36Sopenharmony_ci 222862306a36Sopenharmony_ci if ((dep->flags & DWC3_EP_DELAY_START) && 222962306a36Sopenharmony_ci !usb_endpoint_xfer_isoc(dep->endpoint.desc)) 223062306a36Sopenharmony_ci __dwc3_gadget_kick_transfer(dep); 223162306a36Sopenharmony_ci 223262306a36Sopenharmony_ci dep->flags &= ~DWC3_EP_DELAY_START; 223362306a36Sopenharmony_ci } 223462306a36Sopenharmony_ci 223562306a36Sopenharmony_ci return ret; 223662306a36Sopenharmony_ci} 223762306a36Sopenharmony_ci 223862306a36Sopenharmony_cistatic int dwc3_gadget_ep_set_halt(struct usb_ep *ep, int value) 223962306a36Sopenharmony_ci{ 224062306a36Sopenharmony_ci struct dwc3_ep *dep = to_dwc3_ep(ep); 224162306a36Sopenharmony_ci struct dwc3 *dwc = dep->dwc; 224262306a36Sopenharmony_ci 224362306a36Sopenharmony_ci unsigned long flags; 224462306a36Sopenharmony_ci 224562306a36Sopenharmony_ci int ret; 224662306a36Sopenharmony_ci 224762306a36Sopenharmony_ci spin_lock_irqsave(&dwc->lock, flags); 224862306a36Sopenharmony_ci ret = __dwc3_gadget_ep_set_halt(dep, value, false); 224962306a36Sopenharmony_ci spin_unlock_irqrestore(&dwc->lock, flags); 225062306a36Sopenharmony_ci 225162306a36Sopenharmony_ci return ret; 225262306a36Sopenharmony_ci} 225362306a36Sopenharmony_ci 225462306a36Sopenharmony_cistatic int dwc3_gadget_ep_set_wedge(struct usb_ep *ep) 225562306a36Sopenharmony_ci{ 225662306a36Sopenharmony_ci struct dwc3_ep *dep = to_dwc3_ep(ep); 225762306a36Sopenharmony_ci struct dwc3 *dwc = dep->dwc; 225862306a36Sopenharmony_ci unsigned long flags; 225962306a36Sopenharmony_ci int ret; 226062306a36Sopenharmony_ci 226162306a36Sopenharmony_ci spin_lock_irqsave(&dwc->lock, flags); 226262306a36Sopenharmony_ci dep->flags |= DWC3_EP_WEDGE; 226362306a36Sopenharmony_ci 226462306a36Sopenharmony_ci if (dep->number == 0 || dep->number == 1) 226562306a36Sopenharmony_ci ret = __dwc3_gadget_ep0_set_halt(ep, 1); 226662306a36Sopenharmony_ci else 226762306a36Sopenharmony_ci ret = __dwc3_gadget_ep_set_halt(dep, 1, false); 226862306a36Sopenharmony_ci spin_unlock_irqrestore(&dwc->lock, flags); 226962306a36Sopenharmony_ci 227062306a36Sopenharmony_ci return ret; 227162306a36Sopenharmony_ci} 227262306a36Sopenharmony_ci 227362306a36Sopenharmony_ci/* -------------------------------------------------------------------------- */ 227462306a36Sopenharmony_ci 227562306a36Sopenharmony_cistatic struct usb_endpoint_descriptor dwc3_gadget_ep0_desc = { 227662306a36Sopenharmony_ci .bLength = USB_DT_ENDPOINT_SIZE, 227762306a36Sopenharmony_ci .bDescriptorType = USB_DT_ENDPOINT, 227862306a36Sopenharmony_ci .bmAttributes = USB_ENDPOINT_XFER_CONTROL, 227962306a36Sopenharmony_ci}; 228062306a36Sopenharmony_ci 228162306a36Sopenharmony_cistatic const struct usb_ep_ops dwc3_gadget_ep0_ops = { 228262306a36Sopenharmony_ci .enable = dwc3_gadget_ep0_enable, 228362306a36Sopenharmony_ci .disable = dwc3_gadget_ep0_disable, 228462306a36Sopenharmony_ci .alloc_request = dwc3_gadget_ep_alloc_request, 228562306a36Sopenharmony_ci .free_request = dwc3_gadget_ep_free_request, 228662306a36Sopenharmony_ci .queue = dwc3_gadget_ep0_queue, 228762306a36Sopenharmony_ci .dequeue = dwc3_gadget_ep_dequeue, 228862306a36Sopenharmony_ci .set_halt = dwc3_gadget_ep0_set_halt, 228962306a36Sopenharmony_ci .set_wedge = dwc3_gadget_ep_set_wedge, 229062306a36Sopenharmony_ci}; 229162306a36Sopenharmony_ci 229262306a36Sopenharmony_cistatic const struct usb_ep_ops dwc3_gadget_ep_ops = { 229362306a36Sopenharmony_ci .enable = dwc3_gadget_ep_enable, 229462306a36Sopenharmony_ci .disable = dwc3_gadget_ep_disable, 229562306a36Sopenharmony_ci .alloc_request = dwc3_gadget_ep_alloc_request, 229662306a36Sopenharmony_ci .free_request = dwc3_gadget_ep_free_request, 229762306a36Sopenharmony_ci .queue = dwc3_gadget_ep_queue, 229862306a36Sopenharmony_ci .dequeue = dwc3_gadget_ep_dequeue, 229962306a36Sopenharmony_ci .set_halt = dwc3_gadget_ep_set_halt, 230062306a36Sopenharmony_ci .set_wedge = dwc3_gadget_ep_set_wedge, 230162306a36Sopenharmony_ci}; 230262306a36Sopenharmony_ci 230362306a36Sopenharmony_ci/* -------------------------------------------------------------------------- */ 230462306a36Sopenharmony_ci 230562306a36Sopenharmony_cistatic void dwc3_gadget_enable_linksts_evts(struct dwc3 *dwc, bool set) 230662306a36Sopenharmony_ci{ 230762306a36Sopenharmony_ci u32 reg; 230862306a36Sopenharmony_ci 230962306a36Sopenharmony_ci if (DWC3_VER_IS_PRIOR(DWC3, 250A)) 231062306a36Sopenharmony_ci return; 231162306a36Sopenharmony_ci 231262306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_DEVTEN); 231362306a36Sopenharmony_ci if (set) 231462306a36Sopenharmony_ci reg |= DWC3_DEVTEN_ULSTCNGEN; 231562306a36Sopenharmony_ci else 231662306a36Sopenharmony_ci reg &= ~DWC3_DEVTEN_ULSTCNGEN; 231762306a36Sopenharmony_ci 231862306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_DEVTEN, reg); 231962306a36Sopenharmony_ci} 232062306a36Sopenharmony_ci 232162306a36Sopenharmony_cistatic int dwc3_gadget_get_frame(struct usb_gadget *g) 232262306a36Sopenharmony_ci{ 232362306a36Sopenharmony_ci struct dwc3 *dwc = gadget_to_dwc(g); 232462306a36Sopenharmony_ci 232562306a36Sopenharmony_ci return __dwc3_gadget_get_frame(dwc); 232662306a36Sopenharmony_ci} 232762306a36Sopenharmony_ci 232862306a36Sopenharmony_cistatic int __dwc3_gadget_wakeup(struct dwc3 *dwc, bool async) 232962306a36Sopenharmony_ci{ 233062306a36Sopenharmony_ci int retries; 233162306a36Sopenharmony_ci 233262306a36Sopenharmony_ci int ret; 233362306a36Sopenharmony_ci u32 reg; 233462306a36Sopenharmony_ci 233562306a36Sopenharmony_ci u8 link_state; 233662306a36Sopenharmony_ci 233762306a36Sopenharmony_ci /* 233862306a36Sopenharmony_ci * According to the Databook Remote wakeup request should 233962306a36Sopenharmony_ci * be issued only when the device is in early suspend state. 234062306a36Sopenharmony_ci * 234162306a36Sopenharmony_ci * We can check that via USB Link State bits in DSTS register. 234262306a36Sopenharmony_ci */ 234362306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_DSTS); 234462306a36Sopenharmony_ci 234562306a36Sopenharmony_ci link_state = DWC3_DSTS_USBLNKST(reg); 234662306a36Sopenharmony_ci 234762306a36Sopenharmony_ci switch (link_state) { 234862306a36Sopenharmony_ci case DWC3_LINK_STATE_RESET: 234962306a36Sopenharmony_ci case DWC3_LINK_STATE_RX_DET: /* in HS, means Early Suspend */ 235062306a36Sopenharmony_ci case DWC3_LINK_STATE_U3: /* in HS, means SUSPEND */ 235162306a36Sopenharmony_ci case DWC3_LINK_STATE_U2: /* in HS, means Sleep (L1) */ 235262306a36Sopenharmony_ci case DWC3_LINK_STATE_U1: 235362306a36Sopenharmony_ci case DWC3_LINK_STATE_RESUME: 235462306a36Sopenharmony_ci break; 235562306a36Sopenharmony_ci default: 235662306a36Sopenharmony_ci return -EINVAL; 235762306a36Sopenharmony_ci } 235862306a36Sopenharmony_ci 235962306a36Sopenharmony_ci if (async) 236062306a36Sopenharmony_ci dwc3_gadget_enable_linksts_evts(dwc, true); 236162306a36Sopenharmony_ci 236262306a36Sopenharmony_ci ret = dwc3_gadget_set_link_state(dwc, DWC3_LINK_STATE_RECOV); 236362306a36Sopenharmony_ci if (ret < 0) { 236462306a36Sopenharmony_ci dev_err(dwc->dev, "failed to put link in Recovery\n"); 236562306a36Sopenharmony_ci dwc3_gadget_enable_linksts_evts(dwc, false); 236662306a36Sopenharmony_ci return ret; 236762306a36Sopenharmony_ci } 236862306a36Sopenharmony_ci 236962306a36Sopenharmony_ci /* Recent versions do this automatically */ 237062306a36Sopenharmony_ci if (DWC3_VER_IS_PRIOR(DWC3, 194A)) { 237162306a36Sopenharmony_ci /* write zeroes to Link Change Request */ 237262306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_DCTL); 237362306a36Sopenharmony_ci reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK; 237462306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_DCTL, reg); 237562306a36Sopenharmony_ci } 237662306a36Sopenharmony_ci 237762306a36Sopenharmony_ci /* 237862306a36Sopenharmony_ci * Since link status change events are enabled we will receive 237962306a36Sopenharmony_ci * an U0 event when wakeup is successful. So bail out. 238062306a36Sopenharmony_ci */ 238162306a36Sopenharmony_ci if (async) 238262306a36Sopenharmony_ci return 0; 238362306a36Sopenharmony_ci 238462306a36Sopenharmony_ci /* poll until Link State changes to ON */ 238562306a36Sopenharmony_ci retries = 20000; 238662306a36Sopenharmony_ci 238762306a36Sopenharmony_ci while (retries--) { 238862306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_DSTS); 238962306a36Sopenharmony_ci 239062306a36Sopenharmony_ci /* in HS, means ON */ 239162306a36Sopenharmony_ci if (DWC3_DSTS_USBLNKST(reg) == DWC3_LINK_STATE_U0) 239262306a36Sopenharmony_ci break; 239362306a36Sopenharmony_ci } 239462306a36Sopenharmony_ci 239562306a36Sopenharmony_ci if (DWC3_DSTS_USBLNKST(reg) != DWC3_LINK_STATE_U0) { 239662306a36Sopenharmony_ci dev_err(dwc->dev, "failed to send remote wakeup\n"); 239762306a36Sopenharmony_ci return -EINVAL; 239862306a36Sopenharmony_ci } 239962306a36Sopenharmony_ci 240062306a36Sopenharmony_ci return 0; 240162306a36Sopenharmony_ci} 240262306a36Sopenharmony_ci 240362306a36Sopenharmony_cistatic int dwc3_gadget_wakeup(struct usb_gadget *g) 240462306a36Sopenharmony_ci{ 240562306a36Sopenharmony_ci struct dwc3 *dwc = gadget_to_dwc(g); 240662306a36Sopenharmony_ci unsigned long flags; 240762306a36Sopenharmony_ci int ret; 240862306a36Sopenharmony_ci 240962306a36Sopenharmony_ci if (!dwc->wakeup_configured) { 241062306a36Sopenharmony_ci dev_err(dwc->dev, "remote wakeup not configured\n"); 241162306a36Sopenharmony_ci return -EINVAL; 241262306a36Sopenharmony_ci } 241362306a36Sopenharmony_ci 241462306a36Sopenharmony_ci spin_lock_irqsave(&dwc->lock, flags); 241562306a36Sopenharmony_ci if (!dwc->gadget->wakeup_armed) { 241662306a36Sopenharmony_ci dev_err(dwc->dev, "not armed for remote wakeup\n"); 241762306a36Sopenharmony_ci spin_unlock_irqrestore(&dwc->lock, flags); 241862306a36Sopenharmony_ci return -EINVAL; 241962306a36Sopenharmony_ci } 242062306a36Sopenharmony_ci ret = __dwc3_gadget_wakeup(dwc, true); 242162306a36Sopenharmony_ci 242262306a36Sopenharmony_ci spin_unlock_irqrestore(&dwc->lock, flags); 242362306a36Sopenharmony_ci 242462306a36Sopenharmony_ci return ret; 242562306a36Sopenharmony_ci} 242662306a36Sopenharmony_ci 242762306a36Sopenharmony_cistatic void dwc3_resume_gadget(struct dwc3 *dwc); 242862306a36Sopenharmony_ci 242962306a36Sopenharmony_cistatic int dwc3_gadget_func_wakeup(struct usb_gadget *g, int intf_id) 243062306a36Sopenharmony_ci{ 243162306a36Sopenharmony_ci struct dwc3 *dwc = gadget_to_dwc(g); 243262306a36Sopenharmony_ci unsigned long flags; 243362306a36Sopenharmony_ci int ret; 243462306a36Sopenharmony_ci int link_state; 243562306a36Sopenharmony_ci 243662306a36Sopenharmony_ci if (!dwc->wakeup_configured) { 243762306a36Sopenharmony_ci dev_err(dwc->dev, "remote wakeup not configured\n"); 243862306a36Sopenharmony_ci return -EINVAL; 243962306a36Sopenharmony_ci } 244062306a36Sopenharmony_ci 244162306a36Sopenharmony_ci spin_lock_irqsave(&dwc->lock, flags); 244262306a36Sopenharmony_ci /* 244362306a36Sopenharmony_ci * If the link is in U3, signal for remote wakeup and wait for the 244462306a36Sopenharmony_ci * link to transition to U0 before sending device notification. 244562306a36Sopenharmony_ci */ 244662306a36Sopenharmony_ci link_state = dwc3_gadget_get_link_state(dwc); 244762306a36Sopenharmony_ci if (link_state == DWC3_LINK_STATE_U3) { 244862306a36Sopenharmony_ci ret = __dwc3_gadget_wakeup(dwc, false); 244962306a36Sopenharmony_ci if (ret) { 245062306a36Sopenharmony_ci spin_unlock_irqrestore(&dwc->lock, flags); 245162306a36Sopenharmony_ci return -EINVAL; 245262306a36Sopenharmony_ci } 245362306a36Sopenharmony_ci dwc3_resume_gadget(dwc); 245462306a36Sopenharmony_ci dwc->suspended = false; 245562306a36Sopenharmony_ci dwc->link_state = DWC3_LINK_STATE_U0; 245662306a36Sopenharmony_ci } 245762306a36Sopenharmony_ci 245862306a36Sopenharmony_ci ret = dwc3_send_gadget_generic_command(dwc, DWC3_DGCMD_DEV_NOTIFICATION, 245962306a36Sopenharmony_ci DWC3_DGCMDPAR_DN_FUNC_WAKE | 246062306a36Sopenharmony_ci DWC3_DGCMDPAR_INTF_SEL(intf_id)); 246162306a36Sopenharmony_ci if (ret) 246262306a36Sopenharmony_ci dev_err(dwc->dev, "function remote wakeup failed, ret:%d\n", ret); 246362306a36Sopenharmony_ci 246462306a36Sopenharmony_ci spin_unlock_irqrestore(&dwc->lock, flags); 246562306a36Sopenharmony_ci 246662306a36Sopenharmony_ci return ret; 246762306a36Sopenharmony_ci} 246862306a36Sopenharmony_ci 246962306a36Sopenharmony_cistatic int dwc3_gadget_set_remote_wakeup(struct usb_gadget *g, int set) 247062306a36Sopenharmony_ci{ 247162306a36Sopenharmony_ci struct dwc3 *dwc = gadget_to_dwc(g); 247262306a36Sopenharmony_ci unsigned long flags; 247362306a36Sopenharmony_ci 247462306a36Sopenharmony_ci spin_lock_irqsave(&dwc->lock, flags); 247562306a36Sopenharmony_ci dwc->wakeup_configured = !!set; 247662306a36Sopenharmony_ci spin_unlock_irqrestore(&dwc->lock, flags); 247762306a36Sopenharmony_ci 247862306a36Sopenharmony_ci return 0; 247962306a36Sopenharmony_ci} 248062306a36Sopenharmony_ci 248162306a36Sopenharmony_cistatic int dwc3_gadget_set_selfpowered(struct usb_gadget *g, 248262306a36Sopenharmony_ci int is_selfpowered) 248362306a36Sopenharmony_ci{ 248462306a36Sopenharmony_ci struct dwc3 *dwc = gadget_to_dwc(g); 248562306a36Sopenharmony_ci unsigned long flags; 248662306a36Sopenharmony_ci 248762306a36Sopenharmony_ci spin_lock_irqsave(&dwc->lock, flags); 248862306a36Sopenharmony_ci g->is_selfpowered = !!is_selfpowered; 248962306a36Sopenharmony_ci spin_unlock_irqrestore(&dwc->lock, flags); 249062306a36Sopenharmony_ci 249162306a36Sopenharmony_ci return 0; 249262306a36Sopenharmony_ci} 249362306a36Sopenharmony_ci 249462306a36Sopenharmony_cistatic void dwc3_stop_active_transfers(struct dwc3 *dwc) 249562306a36Sopenharmony_ci{ 249662306a36Sopenharmony_ci u32 epnum; 249762306a36Sopenharmony_ci 249862306a36Sopenharmony_ci for (epnum = 2; epnum < dwc->num_eps; epnum++) { 249962306a36Sopenharmony_ci struct dwc3_ep *dep; 250062306a36Sopenharmony_ci 250162306a36Sopenharmony_ci dep = dwc->eps[epnum]; 250262306a36Sopenharmony_ci if (!dep) 250362306a36Sopenharmony_ci continue; 250462306a36Sopenharmony_ci 250562306a36Sopenharmony_ci dwc3_remove_requests(dwc, dep, -ESHUTDOWN); 250662306a36Sopenharmony_ci } 250762306a36Sopenharmony_ci} 250862306a36Sopenharmony_ci 250962306a36Sopenharmony_cistatic void __dwc3_gadget_set_ssp_rate(struct dwc3 *dwc) 251062306a36Sopenharmony_ci{ 251162306a36Sopenharmony_ci enum usb_ssp_rate ssp_rate = dwc->gadget_ssp_rate; 251262306a36Sopenharmony_ci u32 reg; 251362306a36Sopenharmony_ci 251462306a36Sopenharmony_ci if (ssp_rate == USB_SSP_GEN_UNKNOWN) 251562306a36Sopenharmony_ci ssp_rate = dwc->max_ssp_rate; 251662306a36Sopenharmony_ci 251762306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_DCFG); 251862306a36Sopenharmony_ci reg &= ~DWC3_DCFG_SPEED_MASK; 251962306a36Sopenharmony_ci reg &= ~DWC3_DCFG_NUMLANES(~0); 252062306a36Sopenharmony_ci 252162306a36Sopenharmony_ci if (ssp_rate == USB_SSP_GEN_1x2) 252262306a36Sopenharmony_ci reg |= DWC3_DCFG_SUPERSPEED; 252362306a36Sopenharmony_ci else if (dwc->max_ssp_rate != USB_SSP_GEN_1x2) 252462306a36Sopenharmony_ci reg |= DWC3_DCFG_SUPERSPEED_PLUS; 252562306a36Sopenharmony_ci 252662306a36Sopenharmony_ci if (ssp_rate != USB_SSP_GEN_2x1 && 252762306a36Sopenharmony_ci dwc->max_ssp_rate != USB_SSP_GEN_2x1) 252862306a36Sopenharmony_ci reg |= DWC3_DCFG_NUMLANES(1); 252962306a36Sopenharmony_ci 253062306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_DCFG, reg); 253162306a36Sopenharmony_ci} 253262306a36Sopenharmony_ci 253362306a36Sopenharmony_cistatic void __dwc3_gadget_set_speed(struct dwc3 *dwc) 253462306a36Sopenharmony_ci{ 253562306a36Sopenharmony_ci enum usb_device_speed speed; 253662306a36Sopenharmony_ci u32 reg; 253762306a36Sopenharmony_ci 253862306a36Sopenharmony_ci speed = dwc->gadget_max_speed; 253962306a36Sopenharmony_ci if (speed == USB_SPEED_UNKNOWN || speed > dwc->maximum_speed) 254062306a36Sopenharmony_ci speed = dwc->maximum_speed; 254162306a36Sopenharmony_ci 254262306a36Sopenharmony_ci if (speed == USB_SPEED_SUPER_PLUS && 254362306a36Sopenharmony_ci DWC3_IP_IS(DWC32)) { 254462306a36Sopenharmony_ci __dwc3_gadget_set_ssp_rate(dwc); 254562306a36Sopenharmony_ci return; 254662306a36Sopenharmony_ci } 254762306a36Sopenharmony_ci 254862306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_DCFG); 254962306a36Sopenharmony_ci reg &= ~(DWC3_DCFG_SPEED_MASK); 255062306a36Sopenharmony_ci 255162306a36Sopenharmony_ci /* 255262306a36Sopenharmony_ci * WORKAROUND: DWC3 revision < 2.20a have an issue 255362306a36Sopenharmony_ci * which would cause metastability state on Run/Stop 255462306a36Sopenharmony_ci * bit if we try to force the IP to USB2-only mode. 255562306a36Sopenharmony_ci * 255662306a36Sopenharmony_ci * Because of that, we cannot configure the IP to any 255762306a36Sopenharmony_ci * speed other than the SuperSpeed 255862306a36Sopenharmony_ci * 255962306a36Sopenharmony_ci * Refers to: 256062306a36Sopenharmony_ci * 256162306a36Sopenharmony_ci * STAR#9000525659: Clock Domain Crossing on DCTL in 256262306a36Sopenharmony_ci * USB 2.0 Mode 256362306a36Sopenharmony_ci */ 256462306a36Sopenharmony_ci if (DWC3_VER_IS_PRIOR(DWC3, 220A) && 256562306a36Sopenharmony_ci !dwc->dis_metastability_quirk) { 256662306a36Sopenharmony_ci reg |= DWC3_DCFG_SUPERSPEED; 256762306a36Sopenharmony_ci } else { 256862306a36Sopenharmony_ci switch (speed) { 256962306a36Sopenharmony_ci case USB_SPEED_FULL: 257062306a36Sopenharmony_ci reg |= DWC3_DCFG_FULLSPEED; 257162306a36Sopenharmony_ci break; 257262306a36Sopenharmony_ci case USB_SPEED_HIGH: 257362306a36Sopenharmony_ci reg |= DWC3_DCFG_HIGHSPEED; 257462306a36Sopenharmony_ci break; 257562306a36Sopenharmony_ci case USB_SPEED_SUPER: 257662306a36Sopenharmony_ci reg |= DWC3_DCFG_SUPERSPEED; 257762306a36Sopenharmony_ci break; 257862306a36Sopenharmony_ci case USB_SPEED_SUPER_PLUS: 257962306a36Sopenharmony_ci if (DWC3_IP_IS(DWC3)) 258062306a36Sopenharmony_ci reg |= DWC3_DCFG_SUPERSPEED; 258162306a36Sopenharmony_ci else 258262306a36Sopenharmony_ci reg |= DWC3_DCFG_SUPERSPEED_PLUS; 258362306a36Sopenharmony_ci break; 258462306a36Sopenharmony_ci default: 258562306a36Sopenharmony_ci dev_err(dwc->dev, "invalid speed (%d)\n", speed); 258662306a36Sopenharmony_ci 258762306a36Sopenharmony_ci if (DWC3_IP_IS(DWC3)) 258862306a36Sopenharmony_ci reg |= DWC3_DCFG_SUPERSPEED; 258962306a36Sopenharmony_ci else 259062306a36Sopenharmony_ci reg |= DWC3_DCFG_SUPERSPEED_PLUS; 259162306a36Sopenharmony_ci } 259262306a36Sopenharmony_ci } 259362306a36Sopenharmony_ci 259462306a36Sopenharmony_ci if (DWC3_IP_IS(DWC32) && 259562306a36Sopenharmony_ci speed > USB_SPEED_UNKNOWN && 259662306a36Sopenharmony_ci speed < USB_SPEED_SUPER_PLUS) 259762306a36Sopenharmony_ci reg &= ~DWC3_DCFG_NUMLANES(~0); 259862306a36Sopenharmony_ci 259962306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_DCFG, reg); 260062306a36Sopenharmony_ci} 260162306a36Sopenharmony_ci 260262306a36Sopenharmony_cistatic int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on) 260362306a36Sopenharmony_ci{ 260462306a36Sopenharmony_ci u32 reg; 260562306a36Sopenharmony_ci u32 timeout = 2000; 260662306a36Sopenharmony_ci 260762306a36Sopenharmony_ci if (pm_runtime_suspended(dwc->dev)) 260862306a36Sopenharmony_ci return 0; 260962306a36Sopenharmony_ci 261062306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_DCTL); 261162306a36Sopenharmony_ci if (is_on) { 261262306a36Sopenharmony_ci if (DWC3_VER_IS_WITHIN(DWC3, ANY, 187A)) { 261362306a36Sopenharmony_ci reg &= ~DWC3_DCTL_TRGTULST_MASK; 261462306a36Sopenharmony_ci reg |= DWC3_DCTL_TRGTULST_RX_DET; 261562306a36Sopenharmony_ci } 261662306a36Sopenharmony_ci 261762306a36Sopenharmony_ci if (!DWC3_VER_IS_PRIOR(DWC3, 194A)) 261862306a36Sopenharmony_ci reg &= ~DWC3_DCTL_KEEP_CONNECT; 261962306a36Sopenharmony_ci reg |= DWC3_DCTL_RUN_STOP; 262062306a36Sopenharmony_ci 262162306a36Sopenharmony_ci __dwc3_gadget_set_speed(dwc); 262262306a36Sopenharmony_ci dwc->pullups_connected = true; 262362306a36Sopenharmony_ci } else { 262462306a36Sopenharmony_ci reg &= ~DWC3_DCTL_RUN_STOP; 262562306a36Sopenharmony_ci 262662306a36Sopenharmony_ci dwc->pullups_connected = false; 262762306a36Sopenharmony_ci } 262862306a36Sopenharmony_ci 262962306a36Sopenharmony_ci dwc3_gadget_dctl_write_safe(dwc, reg); 263062306a36Sopenharmony_ci 263162306a36Sopenharmony_ci do { 263262306a36Sopenharmony_ci usleep_range(1000, 2000); 263362306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_DSTS); 263462306a36Sopenharmony_ci reg &= DWC3_DSTS_DEVCTRLHLT; 263562306a36Sopenharmony_ci } while (--timeout && !(!is_on ^ !reg)); 263662306a36Sopenharmony_ci 263762306a36Sopenharmony_ci if (!timeout) 263862306a36Sopenharmony_ci return -ETIMEDOUT; 263962306a36Sopenharmony_ci 264062306a36Sopenharmony_ci return 0; 264162306a36Sopenharmony_ci} 264262306a36Sopenharmony_ci 264362306a36Sopenharmony_cistatic void dwc3_gadget_disable_irq(struct dwc3 *dwc); 264462306a36Sopenharmony_cistatic void __dwc3_gadget_stop(struct dwc3 *dwc); 264562306a36Sopenharmony_cistatic int __dwc3_gadget_start(struct dwc3 *dwc); 264662306a36Sopenharmony_ci 264762306a36Sopenharmony_cistatic int dwc3_gadget_soft_disconnect(struct dwc3 *dwc) 264862306a36Sopenharmony_ci{ 264962306a36Sopenharmony_ci unsigned long flags; 265062306a36Sopenharmony_ci int ret; 265162306a36Sopenharmony_ci 265262306a36Sopenharmony_ci spin_lock_irqsave(&dwc->lock, flags); 265362306a36Sopenharmony_ci if (!dwc->pullups_connected) { 265462306a36Sopenharmony_ci spin_unlock_irqrestore(&dwc->lock, flags); 265562306a36Sopenharmony_ci return 0; 265662306a36Sopenharmony_ci } 265762306a36Sopenharmony_ci 265862306a36Sopenharmony_ci dwc->connected = false; 265962306a36Sopenharmony_ci 266062306a36Sopenharmony_ci /* 266162306a36Sopenharmony_ci * Attempt to end pending SETUP status phase, and not wait for the 266262306a36Sopenharmony_ci * function to do so. 266362306a36Sopenharmony_ci */ 266462306a36Sopenharmony_ci if (dwc->delayed_status) 266562306a36Sopenharmony_ci dwc3_ep0_send_delayed_status(dwc); 266662306a36Sopenharmony_ci 266762306a36Sopenharmony_ci /* 266862306a36Sopenharmony_ci * In the Synopsys DesignWare Cores USB3 Databook Rev. 3.30a 266962306a36Sopenharmony_ci * Section 4.1.8 Table 4-7, it states that for a device-initiated 267062306a36Sopenharmony_ci * disconnect, the SW needs to ensure that it sends "a DEPENDXFER 267162306a36Sopenharmony_ci * command for any active transfers" before clearing the RunStop 267262306a36Sopenharmony_ci * bit. 267362306a36Sopenharmony_ci */ 267462306a36Sopenharmony_ci dwc3_stop_active_transfers(dwc); 267562306a36Sopenharmony_ci spin_unlock_irqrestore(&dwc->lock, flags); 267662306a36Sopenharmony_ci 267762306a36Sopenharmony_ci /* 267862306a36Sopenharmony_ci * Per databook, when we want to stop the gadget, if a control transfer 267962306a36Sopenharmony_ci * is still in process, complete it and get the core into setup phase. 268062306a36Sopenharmony_ci * In case the host is unresponsive to a SETUP transaction, forcefully 268162306a36Sopenharmony_ci * stall the transfer, and move back to the SETUP phase, so that any 268262306a36Sopenharmony_ci * pending endxfers can be executed. 268362306a36Sopenharmony_ci */ 268462306a36Sopenharmony_ci if (dwc->ep0state != EP0_SETUP_PHASE) { 268562306a36Sopenharmony_ci reinit_completion(&dwc->ep0_in_setup); 268662306a36Sopenharmony_ci 268762306a36Sopenharmony_ci ret = wait_for_completion_timeout(&dwc->ep0_in_setup, 268862306a36Sopenharmony_ci msecs_to_jiffies(DWC3_PULL_UP_TIMEOUT)); 268962306a36Sopenharmony_ci if (ret == 0) { 269062306a36Sopenharmony_ci dev_warn(dwc->dev, "wait for SETUP phase timed out\n"); 269162306a36Sopenharmony_ci spin_lock_irqsave(&dwc->lock, flags); 269262306a36Sopenharmony_ci dwc3_ep0_reset_state(dwc); 269362306a36Sopenharmony_ci spin_unlock_irqrestore(&dwc->lock, flags); 269462306a36Sopenharmony_ci } 269562306a36Sopenharmony_ci } 269662306a36Sopenharmony_ci 269762306a36Sopenharmony_ci /* 269862306a36Sopenharmony_ci * Note: if the GEVNTCOUNT indicates events in the event buffer, the 269962306a36Sopenharmony_ci * driver needs to acknowledge them before the controller can halt. 270062306a36Sopenharmony_ci * Simply let the interrupt handler acknowledges and handle the 270162306a36Sopenharmony_ci * remaining event generated by the controller while polling for 270262306a36Sopenharmony_ci * DSTS.DEVCTLHLT. 270362306a36Sopenharmony_ci */ 270462306a36Sopenharmony_ci ret = dwc3_gadget_run_stop(dwc, false); 270562306a36Sopenharmony_ci 270662306a36Sopenharmony_ci /* 270762306a36Sopenharmony_ci * Stop the gadget after controller is halted, so that if needed, the 270862306a36Sopenharmony_ci * events to update EP0 state can still occur while the run/stop 270962306a36Sopenharmony_ci * routine polls for the halted state. DEVTEN is cleared as part of 271062306a36Sopenharmony_ci * gadget stop. 271162306a36Sopenharmony_ci */ 271262306a36Sopenharmony_ci spin_lock_irqsave(&dwc->lock, flags); 271362306a36Sopenharmony_ci __dwc3_gadget_stop(dwc); 271462306a36Sopenharmony_ci spin_unlock_irqrestore(&dwc->lock, flags); 271562306a36Sopenharmony_ci 271662306a36Sopenharmony_ci return ret; 271762306a36Sopenharmony_ci} 271862306a36Sopenharmony_ci 271962306a36Sopenharmony_cistatic int dwc3_gadget_soft_connect(struct dwc3 *dwc) 272062306a36Sopenharmony_ci{ 272162306a36Sopenharmony_ci int ret; 272262306a36Sopenharmony_ci 272362306a36Sopenharmony_ci /* 272462306a36Sopenharmony_ci * In the Synopsys DWC_usb31 1.90a programming guide section 272562306a36Sopenharmony_ci * 4.1.9, it specifies that for a reconnect after a 272662306a36Sopenharmony_ci * device-initiated disconnect requires a core soft reset 272762306a36Sopenharmony_ci * (DCTL.CSftRst) before enabling the run/stop bit. 272862306a36Sopenharmony_ci */ 272962306a36Sopenharmony_ci ret = dwc3_core_soft_reset(dwc); 273062306a36Sopenharmony_ci if (ret) 273162306a36Sopenharmony_ci return ret; 273262306a36Sopenharmony_ci 273362306a36Sopenharmony_ci dwc3_event_buffers_setup(dwc); 273462306a36Sopenharmony_ci __dwc3_gadget_start(dwc); 273562306a36Sopenharmony_ci return dwc3_gadget_run_stop(dwc, true); 273662306a36Sopenharmony_ci} 273762306a36Sopenharmony_ci 273862306a36Sopenharmony_cistatic int dwc3_gadget_pullup(struct usb_gadget *g, int is_on) 273962306a36Sopenharmony_ci{ 274062306a36Sopenharmony_ci struct dwc3 *dwc = gadget_to_dwc(g); 274162306a36Sopenharmony_ci int ret; 274262306a36Sopenharmony_ci 274362306a36Sopenharmony_ci is_on = !!is_on; 274462306a36Sopenharmony_ci 274562306a36Sopenharmony_ci dwc->softconnect = is_on; 274662306a36Sopenharmony_ci 274762306a36Sopenharmony_ci /* 274862306a36Sopenharmony_ci * Avoid issuing a runtime resume if the device is already in the 274962306a36Sopenharmony_ci * suspended state during gadget disconnect. DWC3 gadget was already 275062306a36Sopenharmony_ci * halted/stopped during runtime suspend. 275162306a36Sopenharmony_ci */ 275262306a36Sopenharmony_ci if (!is_on) { 275362306a36Sopenharmony_ci pm_runtime_barrier(dwc->dev); 275462306a36Sopenharmony_ci if (pm_runtime_suspended(dwc->dev)) 275562306a36Sopenharmony_ci return 0; 275662306a36Sopenharmony_ci } 275762306a36Sopenharmony_ci 275862306a36Sopenharmony_ci /* 275962306a36Sopenharmony_ci * Check the return value for successful resume, or error. For a 276062306a36Sopenharmony_ci * successful resume, the DWC3 runtime PM resume routine will handle 276162306a36Sopenharmony_ci * the run stop sequence, so avoid duplicate operations here. 276262306a36Sopenharmony_ci */ 276362306a36Sopenharmony_ci ret = pm_runtime_get_sync(dwc->dev); 276462306a36Sopenharmony_ci if (!ret || ret < 0) { 276562306a36Sopenharmony_ci pm_runtime_put(dwc->dev); 276662306a36Sopenharmony_ci if (ret < 0) 276762306a36Sopenharmony_ci pm_runtime_set_suspended(dwc->dev); 276862306a36Sopenharmony_ci return ret; 276962306a36Sopenharmony_ci } 277062306a36Sopenharmony_ci 277162306a36Sopenharmony_ci if (dwc->pullups_connected == is_on) { 277262306a36Sopenharmony_ci pm_runtime_put(dwc->dev); 277362306a36Sopenharmony_ci return 0; 277462306a36Sopenharmony_ci } 277562306a36Sopenharmony_ci 277662306a36Sopenharmony_ci synchronize_irq(dwc->irq_gadget); 277762306a36Sopenharmony_ci 277862306a36Sopenharmony_ci if (!is_on) 277962306a36Sopenharmony_ci ret = dwc3_gadget_soft_disconnect(dwc); 278062306a36Sopenharmony_ci else 278162306a36Sopenharmony_ci ret = dwc3_gadget_soft_connect(dwc); 278262306a36Sopenharmony_ci 278362306a36Sopenharmony_ci pm_runtime_put(dwc->dev); 278462306a36Sopenharmony_ci 278562306a36Sopenharmony_ci return ret; 278662306a36Sopenharmony_ci} 278762306a36Sopenharmony_ci 278862306a36Sopenharmony_cistatic void dwc3_gadget_enable_irq(struct dwc3 *dwc) 278962306a36Sopenharmony_ci{ 279062306a36Sopenharmony_ci u32 reg; 279162306a36Sopenharmony_ci 279262306a36Sopenharmony_ci /* Enable all but Start and End of Frame IRQs */ 279362306a36Sopenharmony_ci reg = (DWC3_DEVTEN_EVNTOVERFLOWEN | 279462306a36Sopenharmony_ci DWC3_DEVTEN_CMDCMPLTEN | 279562306a36Sopenharmony_ci DWC3_DEVTEN_ERRTICERREN | 279662306a36Sopenharmony_ci DWC3_DEVTEN_WKUPEVTEN | 279762306a36Sopenharmony_ci DWC3_DEVTEN_CONNECTDONEEN | 279862306a36Sopenharmony_ci DWC3_DEVTEN_USBRSTEN | 279962306a36Sopenharmony_ci DWC3_DEVTEN_DISCONNEVTEN); 280062306a36Sopenharmony_ci 280162306a36Sopenharmony_ci if (DWC3_VER_IS_PRIOR(DWC3, 250A)) 280262306a36Sopenharmony_ci reg |= DWC3_DEVTEN_ULSTCNGEN; 280362306a36Sopenharmony_ci 280462306a36Sopenharmony_ci /* On 2.30a and above this bit enables U3/L2-L1 Suspend Events */ 280562306a36Sopenharmony_ci if (!DWC3_VER_IS_PRIOR(DWC3, 230A)) 280662306a36Sopenharmony_ci reg |= DWC3_DEVTEN_U3L2L1SUSPEN; 280762306a36Sopenharmony_ci 280862306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_DEVTEN, reg); 280962306a36Sopenharmony_ci} 281062306a36Sopenharmony_ci 281162306a36Sopenharmony_cistatic void dwc3_gadget_disable_irq(struct dwc3 *dwc) 281262306a36Sopenharmony_ci{ 281362306a36Sopenharmony_ci /* mask all interrupts */ 281462306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00); 281562306a36Sopenharmony_ci} 281662306a36Sopenharmony_ci 281762306a36Sopenharmony_cistatic irqreturn_t dwc3_interrupt(int irq, void *_dwc); 281862306a36Sopenharmony_cistatic irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc); 281962306a36Sopenharmony_ci 282062306a36Sopenharmony_ci/** 282162306a36Sopenharmony_ci * dwc3_gadget_setup_nump - calculate and initialize NUMP field of %DWC3_DCFG 282262306a36Sopenharmony_ci * @dwc: pointer to our context structure 282362306a36Sopenharmony_ci * 282462306a36Sopenharmony_ci * The following looks like complex but it's actually very simple. In order to 282562306a36Sopenharmony_ci * calculate the number of packets we can burst at once on OUT transfers, we're 282662306a36Sopenharmony_ci * gonna use RxFIFO size. 282762306a36Sopenharmony_ci * 282862306a36Sopenharmony_ci * To calculate RxFIFO size we need two numbers: 282962306a36Sopenharmony_ci * MDWIDTH = size, in bits, of the internal memory bus 283062306a36Sopenharmony_ci * RAM2_DEPTH = depth, in MDWIDTH, of internal RAM2 (where RxFIFO sits) 283162306a36Sopenharmony_ci * 283262306a36Sopenharmony_ci * Given these two numbers, the formula is simple: 283362306a36Sopenharmony_ci * 283462306a36Sopenharmony_ci * RxFIFO Size = (RAM2_DEPTH * MDWIDTH / 8) - 24 - 16; 283562306a36Sopenharmony_ci * 283662306a36Sopenharmony_ci * 24 bytes is for 3x SETUP packets 283762306a36Sopenharmony_ci * 16 bytes is a clock domain crossing tolerance 283862306a36Sopenharmony_ci * 283962306a36Sopenharmony_ci * Given RxFIFO Size, NUMP = RxFIFOSize / 1024; 284062306a36Sopenharmony_ci */ 284162306a36Sopenharmony_cistatic void dwc3_gadget_setup_nump(struct dwc3 *dwc) 284262306a36Sopenharmony_ci{ 284362306a36Sopenharmony_ci u32 ram2_depth; 284462306a36Sopenharmony_ci u32 mdwidth; 284562306a36Sopenharmony_ci u32 nump; 284662306a36Sopenharmony_ci u32 reg; 284762306a36Sopenharmony_ci 284862306a36Sopenharmony_ci ram2_depth = DWC3_GHWPARAMS7_RAM2_DEPTH(dwc->hwparams.hwparams7); 284962306a36Sopenharmony_ci mdwidth = dwc3_mdwidth(dwc); 285062306a36Sopenharmony_ci 285162306a36Sopenharmony_ci nump = ((ram2_depth * mdwidth / 8) - 24 - 16) / 1024; 285262306a36Sopenharmony_ci nump = min_t(u32, nump, 16); 285362306a36Sopenharmony_ci 285462306a36Sopenharmony_ci /* update NumP */ 285562306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_DCFG); 285662306a36Sopenharmony_ci reg &= ~DWC3_DCFG_NUMP_MASK; 285762306a36Sopenharmony_ci reg |= nump << DWC3_DCFG_NUMP_SHIFT; 285862306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_DCFG, reg); 285962306a36Sopenharmony_ci} 286062306a36Sopenharmony_ci 286162306a36Sopenharmony_cistatic int __dwc3_gadget_start(struct dwc3 *dwc) 286262306a36Sopenharmony_ci{ 286362306a36Sopenharmony_ci struct dwc3_ep *dep; 286462306a36Sopenharmony_ci int ret = 0; 286562306a36Sopenharmony_ci u32 reg; 286662306a36Sopenharmony_ci 286762306a36Sopenharmony_ci /* 286862306a36Sopenharmony_ci * Use IMOD if enabled via dwc->imod_interval. Otherwise, if 286962306a36Sopenharmony_ci * the core supports IMOD, disable it. 287062306a36Sopenharmony_ci */ 287162306a36Sopenharmony_ci if (dwc->imod_interval) { 287262306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_DEV_IMOD(0), dwc->imod_interval); 287362306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), DWC3_GEVNTCOUNT_EHB); 287462306a36Sopenharmony_ci } else if (dwc3_has_imod(dwc)) { 287562306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_DEV_IMOD(0), 0); 287662306a36Sopenharmony_ci } 287762306a36Sopenharmony_ci 287862306a36Sopenharmony_ci /* 287962306a36Sopenharmony_ci * We are telling dwc3 that we want to use DCFG.NUMP as ACK TP's NUMP 288062306a36Sopenharmony_ci * field instead of letting dwc3 itself calculate that automatically. 288162306a36Sopenharmony_ci * 288262306a36Sopenharmony_ci * This way, we maximize the chances that we'll be able to get several 288362306a36Sopenharmony_ci * bursts of data without going through any sort of endpoint throttling. 288462306a36Sopenharmony_ci */ 288562306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_GRXTHRCFG); 288662306a36Sopenharmony_ci if (DWC3_IP_IS(DWC3)) 288762306a36Sopenharmony_ci reg &= ~DWC3_GRXTHRCFG_PKTCNTSEL; 288862306a36Sopenharmony_ci else 288962306a36Sopenharmony_ci reg &= ~DWC31_GRXTHRCFG_PKTCNTSEL; 289062306a36Sopenharmony_ci 289162306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg); 289262306a36Sopenharmony_ci 289362306a36Sopenharmony_ci dwc3_gadget_setup_nump(dwc); 289462306a36Sopenharmony_ci 289562306a36Sopenharmony_ci /* 289662306a36Sopenharmony_ci * Currently the controller handles single stream only. So, Ignore 289762306a36Sopenharmony_ci * Packet Pending bit for stream selection and don't search for another 289862306a36Sopenharmony_ci * stream if the host sends Data Packet with PP=0 (for OUT direction) or 289962306a36Sopenharmony_ci * ACK with NumP=0 and PP=0 (for IN direction). This slightly improves 290062306a36Sopenharmony_ci * the stream performance. 290162306a36Sopenharmony_ci */ 290262306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_DCFG); 290362306a36Sopenharmony_ci reg |= DWC3_DCFG_IGNSTRMPP; 290462306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_DCFG, reg); 290562306a36Sopenharmony_ci 290662306a36Sopenharmony_ci /* Enable MST by default if the device is capable of MST */ 290762306a36Sopenharmony_ci if (DWC3_MST_CAPABLE(&dwc->hwparams)) { 290862306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_DCFG1); 290962306a36Sopenharmony_ci reg &= ~DWC3_DCFG1_DIS_MST_ENH; 291062306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_DCFG1, reg); 291162306a36Sopenharmony_ci } 291262306a36Sopenharmony_ci 291362306a36Sopenharmony_ci /* Start with SuperSpeed Default */ 291462306a36Sopenharmony_ci dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512); 291562306a36Sopenharmony_ci 291662306a36Sopenharmony_ci dep = dwc->eps[0]; 291762306a36Sopenharmony_ci dep->flags = 0; 291862306a36Sopenharmony_ci ret = __dwc3_gadget_ep_enable(dep, DWC3_DEPCFG_ACTION_INIT); 291962306a36Sopenharmony_ci if (ret) { 292062306a36Sopenharmony_ci dev_err(dwc->dev, "failed to enable %s\n", dep->name); 292162306a36Sopenharmony_ci goto err0; 292262306a36Sopenharmony_ci } 292362306a36Sopenharmony_ci 292462306a36Sopenharmony_ci dep = dwc->eps[1]; 292562306a36Sopenharmony_ci dep->flags = 0; 292662306a36Sopenharmony_ci ret = __dwc3_gadget_ep_enable(dep, DWC3_DEPCFG_ACTION_INIT); 292762306a36Sopenharmony_ci if (ret) { 292862306a36Sopenharmony_ci dev_err(dwc->dev, "failed to enable %s\n", dep->name); 292962306a36Sopenharmony_ci goto err1; 293062306a36Sopenharmony_ci } 293162306a36Sopenharmony_ci 293262306a36Sopenharmony_ci /* begin to receive SETUP packets */ 293362306a36Sopenharmony_ci dwc->ep0state = EP0_SETUP_PHASE; 293462306a36Sopenharmony_ci dwc->ep0_bounced = false; 293562306a36Sopenharmony_ci dwc->link_state = DWC3_LINK_STATE_SS_DIS; 293662306a36Sopenharmony_ci dwc->delayed_status = false; 293762306a36Sopenharmony_ci dwc3_ep0_out_start(dwc); 293862306a36Sopenharmony_ci 293962306a36Sopenharmony_ci dwc3_gadget_enable_irq(dwc); 294062306a36Sopenharmony_ci 294162306a36Sopenharmony_ci return 0; 294262306a36Sopenharmony_ci 294362306a36Sopenharmony_cierr1: 294462306a36Sopenharmony_ci __dwc3_gadget_ep_disable(dwc->eps[0]); 294562306a36Sopenharmony_ci 294662306a36Sopenharmony_cierr0: 294762306a36Sopenharmony_ci return ret; 294862306a36Sopenharmony_ci} 294962306a36Sopenharmony_ci 295062306a36Sopenharmony_cistatic int dwc3_gadget_start(struct usb_gadget *g, 295162306a36Sopenharmony_ci struct usb_gadget_driver *driver) 295262306a36Sopenharmony_ci{ 295362306a36Sopenharmony_ci struct dwc3 *dwc = gadget_to_dwc(g); 295462306a36Sopenharmony_ci unsigned long flags; 295562306a36Sopenharmony_ci int ret; 295662306a36Sopenharmony_ci int irq; 295762306a36Sopenharmony_ci 295862306a36Sopenharmony_ci irq = dwc->irq_gadget; 295962306a36Sopenharmony_ci ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt, 296062306a36Sopenharmony_ci IRQF_SHARED, "dwc3", dwc->ev_buf); 296162306a36Sopenharmony_ci if (ret) { 296262306a36Sopenharmony_ci dev_err(dwc->dev, "failed to request irq #%d --> %d\n", 296362306a36Sopenharmony_ci irq, ret); 296462306a36Sopenharmony_ci return ret; 296562306a36Sopenharmony_ci } 296662306a36Sopenharmony_ci 296762306a36Sopenharmony_ci spin_lock_irqsave(&dwc->lock, flags); 296862306a36Sopenharmony_ci dwc->gadget_driver = driver; 296962306a36Sopenharmony_ci spin_unlock_irqrestore(&dwc->lock, flags); 297062306a36Sopenharmony_ci 297162306a36Sopenharmony_ci return 0; 297262306a36Sopenharmony_ci} 297362306a36Sopenharmony_ci 297462306a36Sopenharmony_cistatic void __dwc3_gadget_stop(struct dwc3 *dwc) 297562306a36Sopenharmony_ci{ 297662306a36Sopenharmony_ci dwc3_gadget_disable_irq(dwc); 297762306a36Sopenharmony_ci __dwc3_gadget_ep_disable(dwc->eps[0]); 297862306a36Sopenharmony_ci __dwc3_gadget_ep_disable(dwc->eps[1]); 297962306a36Sopenharmony_ci} 298062306a36Sopenharmony_ci 298162306a36Sopenharmony_cistatic int dwc3_gadget_stop(struct usb_gadget *g) 298262306a36Sopenharmony_ci{ 298362306a36Sopenharmony_ci struct dwc3 *dwc = gadget_to_dwc(g); 298462306a36Sopenharmony_ci unsigned long flags; 298562306a36Sopenharmony_ci 298662306a36Sopenharmony_ci spin_lock_irqsave(&dwc->lock, flags); 298762306a36Sopenharmony_ci dwc->gadget_driver = NULL; 298862306a36Sopenharmony_ci dwc->max_cfg_eps = 0; 298962306a36Sopenharmony_ci spin_unlock_irqrestore(&dwc->lock, flags); 299062306a36Sopenharmony_ci 299162306a36Sopenharmony_ci free_irq(dwc->irq_gadget, dwc->ev_buf); 299262306a36Sopenharmony_ci 299362306a36Sopenharmony_ci return 0; 299462306a36Sopenharmony_ci} 299562306a36Sopenharmony_ci 299662306a36Sopenharmony_cistatic void dwc3_gadget_config_params(struct usb_gadget *g, 299762306a36Sopenharmony_ci struct usb_dcd_config_params *params) 299862306a36Sopenharmony_ci{ 299962306a36Sopenharmony_ci struct dwc3 *dwc = gadget_to_dwc(g); 300062306a36Sopenharmony_ci 300162306a36Sopenharmony_ci params->besl_baseline = USB_DEFAULT_BESL_UNSPECIFIED; 300262306a36Sopenharmony_ci params->besl_deep = USB_DEFAULT_BESL_UNSPECIFIED; 300362306a36Sopenharmony_ci 300462306a36Sopenharmony_ci /* Recommended BESL */ 300562306a36Sopenharmony_ci if (!dwc->dis_enblslpm_quirk) { 300662306a36Sopenharmony_ci /* 300762306a36Sopenharmony_ci * If the recommended BESL baseline is 0 or if the BESL deep is 300862306a36Sopenharmony_ci * less than 2, Microsoft's Windows 10 host usb stack will issue 300962306a36Sopenharmony_ci * a usb reset immediately after it receives the extended BOS 301062306a36Sopenharmony_ci * descriptor and the enumeration will fail. To maintain 301162306a36Sopenharmony_ci * compatibility with the Windows' usb stack, let's set the 301262306a36Sopenharmony_ci * recommended BESL baseline to 1 and clamp the BESL deep to be 301362306a36Sopenharmony_ci * within 2 to 15. 301462306a36Sopenharmony_ci */ 301562306a36Sopenharmony_ci params->besl_baseline = 1; 301662306a36Sopenharmony_ci if (dwc->is_utmi_l1_suspend) 301762306a36Sopenharmony_ci params->besl_deep = 301862306a36Sopenharmony_ci clamp_t(u8, dwc->hird_threshold, 2, 15); 301962306a36Sopenharmony_ci } 302062306a36Sopenharmony_ci 302162306a36Sopenharmony_ci /* U1 Device exit Latency */ 302262306a36Sopenharmony_ci if (dwc->dis_u1_entry_quirk) 302362306a36Sopenharmony_ci params->bU1devExitLat = 0; 302462306a36Sopenharmony_ci else 302562306a36Sopenharmony_ci params->bU1devExitLat = DWC3_DEFAULT_U1_DEV_EXIT_LAT; 302662306a36Sopenharmony_ci 302762306a36Sopenharmony_ci /* U2 Device exit Latency */ 302862306a36Sopenharmony_ci if (dwc->dis_u2_entry_quirk) 302962306a36Sopenharmony_ci params->bU2DevExitLat = 0; 303062306a36Sopenharmony_ci else 303162306a36Sopenharmony_ci params->bU2DevExitLat = 303262306a36Sopenharmony_ci cpu_to_le16(DWC3_DEFAULT_U2_DEV_EXIT_LAT); 303362306a36Sopenharmony_ci} 303462306a36Sopenharmony_ci 303562306a36Sopenharmony_cistatic void dwc3_gadget_set_speed(struct usb_gadget *g, 303662306a36Sopenharmony_ci enum usb_device_speed speed) 303762306a36Sopenharmony_ci{ 303862306a36Sopenharmony_ci struct dwc3 *dwc = gadget_to_dwc(g); 303962306a36Sopenharmony_ci unsigned long flags; 304062306a36Sopenharmony_ci 304162306a36Sopenharmony_ci spin_lock_irqsave(&dwc->lock, flags); 304262306a36Sopenharmony_ci dwc->gadget_max_speed = speed; 304362306a36Sopenharmony_ci spin_unlock_irqrestore(&dwc->lock, flags); 304462306a36Sopenharmony_ci} 304562306a36Sopenharmony_ci 304662306a36Sopenharmony_cistatic void dwc3_gadget_set_ssp_rate(struct usb_gadget *g, 304762306a36Sopenharmony_ci enum usb_ssp_rate rate) 304862306a36Sopenharmony_ci{ 304962306a36Sopenharmony_ci struct dwc3 *dwc = gadget_to_dwc(g); 305062306a36Sopenharmony_ci unsigned long flags; 305162306a36Sopenharmony_ci 305262306a36Sopenharmony_ci spin_lock_irqsave(&dwc->lock, flags); 305362306a36Sopenharmony_ci dwc->gadget_max_speed = USB_SPEED_SUPER_PLUS; 305462306a36Sopenharmony_ci dwc->gadget_ssp_rate = rate; 305562306a36Sopenharmony_ci spin_unlock_irqrestore(&dwc->lock, flags); 305662306a36Sopenharmony_ci} 305762306a36Sopenharmony_ci 305862306a36Sopenharmony_cistatic int dwc3_gadget_vbus_draw(struct usb_gadget *g, unsigned int mA) 305962306a36Sopenharmony_ci{ 306062306a36Sopenharmony_ci struct dwc3 *dwc = gadget_to_dwc(g); 306162306a36Sopenharmony_ci union power_supply_propval val = {0}; 306262306a36Sopenharmony_ci int ret; 306362306a36Sopenharmony_ci 306462306a36Sopenharmony_ci if (dwc->usb2_phy) 306562306a36Sopenharmony_ci return usb_phy_set_power(dwc->usb2_phy, mA); 306662306a36Sopenharmony_ci 306762306a36Sopenharmony_ci if (!dwc->usb_psy) 306862306a36Sopenharmony_ci return -EOPNOTSUPP; 306962306a36Sopenharmony_ci 307062306a36Sopenharmony_ci val.intval = 1000 * mA; 307162306a36Sopenharmony_ci ret = power_supply_set_property(dwc->usb_psy, POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, &val); 307262306a36Sopenharmony_ci 307362306a36Sopenharmony_ci return ret; 307462306a36Sopenharmony_ci} 307562306a36Sopenharmony_ci 307662306a36Sopenharmony_ci/** 307762306a36Sopenharmony_ci * dwc3_gadget_check_config - ensure dwc3 can support the USB configuration 307862306a36Sopenharmony_ci * @g: pointer to the USB gadget 307962306a36Sopenharmony_ci * 308062306a36Sopenharmony_ci * Used to record the maximum number of endpoints being used in a USB composite 308162306a36Sopenharmony_ci * device. (across all configurations) This is to be used in the calculation 308262306a36Sopenharmony_ci * of the TXFIFO sizes when resizing internal memory for individual endpoints. 308362306a36Sopenharmony_ci * It will help ensured that the resizing logic reserves enough space for at 308462306a36Sopenharmony_ci * least one max packet. 308562306a36Sopenharmony_ci */ 308662306a36Sopenharmony_cistatic int dwc3_gadget_check_config(struct usb_gadget *g) 308762306a36Sopenharmony_ci{ 308862306a36Sopenharmony_ci struct dwc3 *dwc = gadget_to_dwc(g); 308962306a36Sopenharmony_ci struct usb_ep *ep; 309062306a36Sopenharmony_ci int fifo_size = 0; 309162306a36Sopenharmony_ci int ram1_depth; 309262306a36Sopenharmony_ci int ep_num = 0; 309362306a36Sopenharmony_ci 309462306a36Sopenharmony_ci if (!dwc->do_fifo_resize) 309562306a36Sopenharmony_ci return 0; 309662306a36Sopenharmony_ci 309762306a36Sopenharmony_ci list_for_each_entry(ep, &g->ep_list, ep_list) { 309862306a36Sopenharmony_ci /* Only interested in the IN endpoints */ 309962306a36Sopenharmony_ci if (ep->claimed && (ep->address & USB_DIR_IN)) 310062306a36Sopenharmony_ci ep_num++; 310162306a36Sopenharmony_ci } 310262306a36Sopenharmony_ci 310362306a36Sopenharmony_ci if (ep_num <= dwc->max_cfg_eps) 310462306a36Sopenharmony_ci return 0; 310562306a36Sopenharmony_ci 310662306a36Sopenharmony_ci /* Update the max number of eps in the composition */ 310762306a36Sopenharmony_ci dwc->max_cfg_eps = ep_num; 310862306a36Sopenharmony_ci 310962306a36Sopenharmony_ci fifo_size = dwc3_gadget_calc_tx_fifo_size(dwc, dwc->max_cfg_eps); 311062306a36Sopenharmony_ci /* Based on the equation, increment by one for every ep */ 311162306a36Sopenharmony_ci fifo_size += dwc->max_cfg_eps; 311262306a36Sopenharmony_ci 311362306a36Sopenharmony_ci /* Check if we can fit a single fifo per endpoint */ 311462306a36Sopenharmony_ci ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7); 311562306a36Sopenharmony_ci if (fifo_size > ram1_depth) 311662306a36Sopenharmony_ci return -ENOMEM; 311762306a36Sopenharmony_ci 311862306a36Sopenharmony_ci return 0; 311962306a36Sopenharmony_ci} 312062306a36Sopenharmony_ci 312162306a36Sopenharmony_cistatic void dwc3_gadget_async_callbacks(struct usb_gadget *g, bool enable) 312262306a36Sopenharmony_ci{ 312362306a36Sopenharmony_ci struct dwc3 *dwc = gadget_to_dwc(g); 312462306a36Sopenharmony_ci unsigned long flags; 312562306a36Sopenharmony_ci 312662306a36Sopenharmony_ci spin_lock_irqsave(&dwc->lock, flags); 312762306a36Sopenharmony_ci dwc->async_callbacks = enable; 312862306a36Sopenharmony_ci spin_unlock_irqrestore(&dwc->lock, flags); 312962306a36Sopenharmony_ci} 313062306a36Sopenharmony_ci 313162306a36Sopenharmony_cistatic const struct usb_gadget_ops dwc3_gadget_ops = { 313262306a36Sopenharmony_ci .get_frame = dwc3_gadget_get_frame, 313362306a36Sopenharmony_ci .wakeup = dwc3_gadget_wakeup, 313462306a36Sopenharmony_ci .func_wakeup = dwc3_gadget_func_wakeup, 313562306a36Sopenharmony_ci .set_remote_wakeup = dwc3_gadget_set_remote_wakeup, 313662306a36Sopenharmony_ci .set_selfpowered = dwc3_gadget_set_selfpowered, 313762306a36Sopenharmony_ci .pullup = dwc3_gadget_pullup, 313862306a36Sopenharmony_ci .udc_start = dwc3_gadget_start, 313962306a36Sopenharmony_ci .udc_stop = dwc3_gadget_stop, 314062306a36Sopenharmony_ci .udc_set_speed = dwc3_gadget_set_speed, 314162306a36Sopenharmony_ci .udc_set_ssp_rate = dwc3_gadget_set_ssp_rate, 314262306a36Sopenharmony_ci .get_config_params = dwc3_gadget_config_params, 314362306a36Sopenharmony_ci .vbus_draw = dwc3_gadget_vbus_draw, 314462306a36Sopenharmony_ci .check_config = dwc3_gadget_check_config, 314562306a36Sopenharmony_ci .udc_async_callbacks = dwc3_gadget_async_callbacks, 314662306a36Sopenharmony_ci}; 314762306a36Sopenharmony_ci 314862306a36Sopenharmony_ci/* -------------------------------------------------------------------------- */ 314962306a36Sopenharmony_ci 315062306a36Sopenharmony_cistatic int dwc3_gadget_init_control_endpoint(struct dwc3_ep *dep) 315162306a36Sopenharmony_ci{ 315262306a36Sopenharmony_ci struct dwc3 *dwc = dep->dwc; 315362306a36Sopenharmony_ci 315462306a36Sopenharmony_ci usb_ep_set_maxpacket_limit(&dep->endpoint, 512); 315562306a36Sopenharmony_ci dep->endpoint.maxburst = 1; 315662306a36Sopenharmony_ci dep->endpoint.ops = &dwc3_gadget_ep0_ops; 315762306a36Sopenharmony_ci if (!dep->direction) 315862306a36Sopenharmony_ci dwc->gadget->ep0 = &dep->endpoint; 315962306a36Sopenharmony_ci 316062306a36Sopenharmony_ci dep->endpoint.caps.type_control = true; 316162306a36Sopenharmony_ci 316262306a36Sopenharmony_ci return 0; 316362306a36Sopenharmony_ci} 316462306a36Sopenharmony_ci 316562306a36Sopenharmony_cistatic int dwc3_gadget_init_in_endpoint(struct dwc3_ep *dep) 316662306a36Sopenharmony_ci{ 316762306a36Sopenharmony_ci struct dwc3 *dwc = dep->dwc; 316862306a36Sopenharmony_ci u32 mdwidth; 316962306a36Sopenharmony_ci int size; 317062306a36Sopenharmony_ci int maxpacket; 317162306a36Sopenharmony_ci 317262306a36Sopenharmony_ci mdwidth = dwc3_mdwidth(dwc); 317362306a36Sopenharmony_ci 317462306a36Sopenharmony_ci /* MDWIDTH is represented in bits, we need it in bytes */ 317562306a36Sopenharmony_ci mdwidth /= 8; 317662306a36Sopenharmony_ci 317762306a36Sopenharmony_ci size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(dep->number >> 1)); 317862306a36Sopenharmony_ci if (DWC3_IP_IS(DWC3)) 317962306a36Sopenharmony_ci size = DWC3_GTXFIFOSIZ_TXFDEP(size); 318062306a36Sopenharmony_ci else 318162306a36Sopenharmony_ci size = DWC31_GTXFIFOSIZ_TXFDEP(size); 318262306a36Sopenharmony_ci 318362306a36Sopenharmony_ci /* 318462306a36Sopenharmony_ci * maxpacket size is determined as part of the following, after assuming 318562306a36Sopenharmony_ci * a mult value of one maxpacket: 318662306a36Sopenharmony_ci * DWC3 revision 280A and prior: 318762306a36Sopenharmony_ci * fifo_size = mult * (max_packet / mdwidth) + 1; 318862306a36Sopenharmony_ci * maxpacket = mdwidth * (fifo_size - 1); 318962306a36Sopenharmony_ci * 319062306a36Sopenharmony_ci * DWC3 revision 290A and onwards: 319162306a36Sopenharmony_ci * fifo_size = mult * ((max_packet + mdwidth)/mdwidth + 1) + 1 319262306a36Sopenharmony_ci * maxpacket = mdwidth * ((fifo_size - 1) - 1) - mdwidth; 319362306a36Sopenharmony_ci */ 319462306a36Sopenharmony_ci if (DWC3_VER_IS_PRIOR(DWC3, 290A)) 319562306a36Sopenharmony_ci maxpacket = mdwidth * (size - 1); 319662306a36Sopenharmony_ci else 319762306a36Sopenharmony_ci maxpacket = mdwidth * ((size - 1) - 1) - mdwidth; 319862306a36Sopenharmony_ci 319962306a36Sopenharmony_ci /* Functionally, space for one max packet is sufficient */ 320062306a36Sopenharmony_ci size = min_t(int, maxpacket, 1024); 320162306a36Sopenharmony_ci usb_ep_set_maxpacket_limit(&dep->endpoint, size); 320262306a36Sopenharmony_ci 320362306a36Sopenharmony_ci dep->endpoint.max_streams = 16; 320462306a36Sopenharmony_ci dep->endpoint.ops = &dwc3_gadget_ep_ops; 320562306a36Sopenharmony_ci list_add_tail(&dep->endpoint.ep_list, 320662306a36Sopenharmony_ci &dwc->gadget->ep_list); 320762306a36Sopenharmony_ci dep->endpoint.caps.type_iso = true; 320862306a36Sopenharmony_ci dep->endpoint.caps.type_bulk = true; 320962306a36Sopenharmony_ci dep->endpoint.caps.type_int = true; 321062306a36Sopenharmony_ci 321162306a36Sopenharmony_ci return dwc3_alloc_trb_pool(dep); 321262306a36Sopenharmony_ci} 321362306a36Sopenharmony_ci 321462306a36Sopenharmony_cistatic int dwc3_gadget_init_out_endpoint(struct dwc3_ep *dep) 321562306a36Sopenharmony_ci{ 321662306a36Sopenharmony_ci struct dwc3 *dwc = dep->dwc; 321762306a36Sopenharmony_ci u32 mdwidth; 321862306a36Sopenharmony_ci int size; 321962306a36Sopenharmony_ci 322062306a36Sopenharmony_ci mdwidth = dwc3_mdwidth(dwc); 322162306a36Sopenharmony_ci 322262306a36Sopenharmony_ci /* MDWIDTH is represented in bits, convert to bytes */ 322362306a36Sopenharmony_ci mdwidth /= 8; 322462306a36Sopenharmony_ci 322562306a36Sopenharmony_ci /* All OUT endpoints share a single RxFIFO space */ 322662306a36Sopenharmony_ci size = dwc3_readl(dwc->regs, DWC3_GRXFIFOSIZ(0)); 322762306a36Sopenharmony_ci if (DWC3_IP_IS(DWC3)) 322862306a36Sopenharmony_ci size = DWC3_GRXFIFOSIZ_RXFDEP(size); 322962306a36Sopenharmony_ci else 323062306a36Sopenharmony_ci size = DWC31_GRXFIFOSIZ_RXFDEP(size); 323162306a36Sopenharmony_ci 323262306a36Sopenharmony_ci /* FIFO depth is in MDWDITH bytes */ 323362306a36Sopenharmony_ci size *= mdwidth; 323462306a36Sopenharmony_ci 323562306a36Sopenharmony_ci /* 323662306a36Sopenharmony_ci * To meet performance requirement, a minimum recommended RxFIFO size 323762306a36Sopenharmony_ci * is defined as follow: 323862306a36Sopenharmony_ci * RxFIFO size >= (3 x MaxPacketSize) + 323962306a36Sopenharmony_ci * (3 x 8 bytes setup packets size) + (16 bytes clock crossing margin) 324062306a36Sopenharmony_ci * 324162306a36Sopenharmony_ci * Then calculate the max packet limit as below. 324262306a36Sopenharmony_ci */ 324362306a36Sopenharmony_ci size -= (3 * 8) + 16; 324462306a36Sopenharmony_ci if (size < 0) 324562306a36Sopenharmony_ci size = 0; 324662306a36Sopenharmony_ci else 324762306a36Sopenharmony_ci size /= 3; 324862306a36Sopenharmony_ci 324962306a36Sopenharmony_ci usb_ep_set_maxpacket_limit(&dep->endpoint, size); 325062306a36Sopenharmony_ci dep->endpoint.max_streams = 16; 325162306a36Sopenharmony_ci dep->endpoint.ops = &dwc3_gadget_ep_ops; 325262306a36Sopenharmony_ci list_add_tail(&dep->endpoint.ep_list, 325362306a36Sopenharmony_ci &dwc->gadget->ep_list); 325462306a36Sopenharmony_ci dep->endpoint.caps.type_iso = true; 325562306a36Sopenharmony_ci dep->endpoint.caps.type_bulk = true; 325662306a36Sopenharmony_ci dep->endpoint.caps.type_int = true; 325762306a36Sopenharmony_ci 325862306a36Sopenharmony_ci return dwc3_alloc_trb_pool(dep); 325962306a36Sopenharmony_ci} 326062306a36Sopenharmony_ci 326162306a36Sopenharmony_cistatic int dwc3_gadget_init_endpoint(struct dwc3 *dwc, u8 epnum) 326262306a36Sopenharmony_ci{ 326362306a36Sopenharmony_ci struct dwc3_ep *dep; 326462306a36Sopenharmony_ci bool direction = epnum & 1; 326562306a36Sopenharmony_ci int ret; 326662306a36Sopenharmony_ci u8 num = epnum >> 1; 326762306a36Sopenharmony_ci 326862306a36Sopenharmony_ci dep = kzalloc(sizeof(*dep), GFP_KERNEL); 326962306a36Sopenharmony_ci if (!dep) 327062306a36Sopenharmony_ci return -ENOMEM; 327162306a36Sopenharmony_ci 327262306a36Sopenharmony_ci dep->dwc = dwc; 327362306a36Sopenharmony_ci dep->number = epnum; 327462306a36Sopenharmony_ci dep->direction = direction; 327562306a36Sopenharmony_ci dep->regs = dwc->regs + DWC3_DEP_BASE(epnum); 327662306a36Sopenharmony_ci dwc->eps[epnum] = dep; 327762306a36Sopenharmony_ci dep->combo_num = 0; 327862306a36Sopenharmony_ci dep->start_cmd_status = 0; 327962306a36Sopenharmony_ci 328062306a36Sopenharmony_ci snprintf(dep->name, sizeof(dep->name), "ep%u%s", num, 328162306a36Sopenharmony_ci direction ? "in" : "out"); 328262306a36Sopenharmony_ci 328362306a36Sopenharmony_ci dep->endpoint.name = dep->name; 328462306a36Sopenharmony_ci 328562306a36Sopenharmony_ci if (!(dep->number > 1)) { 328662306a36Sopenharmony_ci dep->endpoint.desc = &dwc3_gadget_ep0_desc; 328762306a36Sopenharmony_ci dep->endpoint.comp_desc = NULL; 328862306a36Sopenharmony_ci } 328962306a36Sopenharmony_ci 329062306a36Sopenharmony_ci if (num == 0) 329162306a36Sopenharmony_ci ret = dwc3_gadget_init_control_endpoint(dep); 329262306a36Sopenharmony_ci else if (direction) 329362306a36Sopenharmony_ci ret = dwc3_gadget_init_in_endpoint(dep); 329462306a36Sopenharmony_ci else 329562306a36Sopenharmony_ci ret = dwc3_gadget_init_out_endpoint(dep); 329662306a36Sopenharmony_ci 329762306a36Sopenharmony_ci if (ret) 329862306a36Sopenharmony_ci return ret; 329962306a36Sopenharmony_ci 330062306a36Sopenharmony_ci dep->endpoint.caps.dir_in = direction; 330162306a36Sopenharmony_ci dep->endpoint.caps.dir_out = !direction; 330262306a36Sopenharmony_ci 330362306a36Sopenharmony_ci INIT_LIST_HEAD(&dep->pending_list); 330462306a36Sopenharmony_ci INIT_LIST_HEAD(&dep->started_list); 330562306a36Sopenharmony_ci INIT_LIST_HEAD(&dep->cancelled_list); 330662306a36Sopenharmony_ci 330762306a36Sopenharmony_ci dwc3_debugfs_create_endpoint_dir(dep); 330862306a36Sopenharmony_ci 330962306a36Sopenharmony_ci return 0; 331062306a36Sopenharmony_ci} 331162306a36Sopenharmony_ci 331262306a36Sopenharmony_cistatic int dwc3_gadget_init_endpoints(struct dwc3 *dwc, u8 total) 331362306a36Sopenharmony_ci{ 331462306a36Sopenharmony_ci u8 epnum; 331562306a36Sopenharmony_ci 331662306a36Sopenharmony_ci INIT_LIST_HEAD(&dwc->gadget->ep_list); 331762306a36Sopenharmony_ci 331862306a36Sopenharmony_ci for (epnum = 0; epnum < total; epnum++) { 331962306a36Sopenharmony_ci int ret; 332062306a36Sopenharmony_ci 332162306a36Sopenharmony_ci ret = dwc3_gadget_init_endpoint(dwc, epnum); 332262306a36Sopenharmony_ci if (ret) 332362306a36Sopenharmony_ci return ret; 332462306a36Sopenharmony_ci } 332562306a36Sopenharmony_ci 332662306a36Sopenharmony_ci return 0; 332762306a36Sopenharmony_ci} 332862306a36Sopenharmony_ci 332962306a36Sopenharmony_cistatic void dwc3_gadget_free_endpoints(struct dwc3 *dwc) 333062306a36Sopenharmony_ci{ 333162306a36Sopenharmony_ci struct dwc3_ep *dep; 333262306a36Sopenharmony_ci u8 epnum; 333362306a36Sopenharmony_ci 333462306a36Sopenharmony_ci for (epnum = 0; epnum < DWC3_ENDPOINTS_NUM; epnum++) { 333562306a36Sopenharmony_ci dep = dwc->eps[epnum]; 333662306a36Sopenharmony_ci if (!dep) 333762306a36Sopenharmony_ci continue; 333862306a36Sopenharmony_ci /* 333962306a36Sopenharmony_ci * Physical endpoints 0 and 1 are special; they form the 334062306a36Sopenharmony_ci * bi-directional USB endpoint 0. 334162306a36Sopenharmony_ci * 334262306a36Sopenharmony_ci * For those two physical endpoints, we don't allocate a TRB 334362306a36Sopenharmony_ci * pool nor do we add them the endpoints list. Due to that, we 334462306a36Sopenharmony_ci * shouldn't do these two operations otherwise we would end up 334562306a36Sopenharmony_ci * with all sorts of bugs when removing dwc3.ko. 334662306a36Sopenharmony_ci */ 334762306a36Sopenharmony_ci if (epnum != 0 && epnum != 1) { 334862306a36Sopenharmony_ci dwc3_free_trb_pool(dep); 334962306a36Sopenharmony_ci list_del(&dep->endpoint.ep_list); 335062306a36Sopenharmony_ci } 335162306a36Sopenharmony_ci 335262306a36Sopenharmony_ci dwc3_debugfs_remove_endpoint_dir(dep); 335362306a36Sopenharmony_ci kfree(dep); 335462306a36Sopenharmony_ci } 335562306a36Sopenharmony_ci} 335662306a36Sopenharmony_ci 335762306a36Sopenharmony_ci/* -------------------------------------------------------------------------- */ 335862306a36Sopenharmony_ci 335962306a36Sopenharmony_cistatic int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep, 336062306a36Sopenharmony_ci struct dwc3_request *req, struct dwc3_trb *trb, 336162306a36Sopenharmony_ci const struct dwc3_event_depevt *event, int status, int chain) 336262306a36Sopenharmony_ci{ 336362306a36Sopenharmony_ci unsigned int count; 336462306a36Sopenharmony_ci 336562306a36Sopenharmony_ci dwc3_ep_inc_deq(dep); 336662306a36Sopenharmony_ci 336762306a36Sopenharmony_ci trace_dwc3_complete_trb(dep, trb); 336862306a36Sopenharmony_ci req->num_trbs--; 336962306a36Sopenharmony_ci 337062306a36Sopenharmony_ci /* 337162306a36Sopenharmony_ci * If we're in the middle of series of chained TRBs and we 337262306a36Sopenharmony_ci * receive a short transfer along the way, DWC3 will skip 337362306a36Sopenharmony_ci * through all TRBs including the last TRB in the chain (the 337462306a36Sopenharmony_ci * where CHN bit is zero. DWC3 will also avoid clearing HWO 337562306a36Sopenharmony_ci * bit and SW has to do it manually. 337662306a36Sopenharmony_ci * 337762306a36Sopenharmony_ci * We're going to do that here to avoid problems of HW trying 337862306a36Sopenharmony_ci * to use bogus TRBs for transfers. 337962306a36Sopenharmony_ci */ 338062306a36Sopenharmony_ci if (chain && (trb->ctrl & DWC3_TRB_CTRL_HWO)) 338162306a36Sopenharmony_ci trb->ctrl &= ~DWC3_TRB_CTRL_HWO; 338262306a36Sopenharmony_ci 338362306a36Sopenharmony_ci /* 338462306a36Sopenharmony_ci * For isochronous transfers, the first TRB in a service interval must 338562306a36Sopenharmony_ci * have the Isoc-First type. Track and report its interval frame number. 338662306a36Sopenharmony_ci */ 338762306a36Sopenharmony_ci if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && 338862306a36Sopenharmony_ci (trb->ctrl & DWC3_TRBCTL_ISOCHRONOUS_FIRST)) { 338962306a36Sopenharmony_ci unsigned int frame_number; 339062306a36Sopenharmony_ci 339162306a36Sopenharmony_ci frame_number = DWC3_TRB_CTRL_GET_SID_SOFN(trb->ctrl); 339262306a36Sopenharmony_ci frame_number &= ~(dep->interval - 1); 339362306a36Sopenharmony_ci req->request.frame_number = frame_number; 339462306a36Sopenharmony_ci } 339562306a36Sopenharmony_ci 339662306a36Sopenharmony_ci /* 339762306a36Sopenharmony_ci * We use bounce buffer for requests that needs extra TRB or OUT ZLP. If 339862306a36Sopenharmony_ci * this TRB points to the bounce buffer address, it's a MPS alignment 339962306a36Sopenharmony_ci * TRB. Don't add it to req->remaining calculation. 340062306a36Sopenharmony_ci */ 340162306a36Sopenharmony_ci if (trb->bpl == lower_32_bits(dep->dwc->bounce_addr) && 340262306a36Sopenharmony_ci trb->bph == upper_32_bits(dep->dwc->bounce_addr)) { 340362306a36Sopenharmony_ci trb->ctrl &= ~DWC3_TRB_CTRL_HWO; 340462306a36Sopenharmony_ci return 1; 340562306a36Sopenharmony_ci } 340662306a36Sopenharmony_ci 340762306a36Sopenharmony_ci count = trb->size & DWC3_TRB_SIZE_MASK; 340862306a36Sopenharmony_ci req->remaining += count; 340962306a36Sopenharmony_ci 341062306a36Sopenharmony_ci if ((trb->ctrl & DWC3_TRB_CTRL_HWO) && status != -ESHUTDOWN) 341162306a36Sopenharmony_ci return 1; 341262306a36Sopenharmony_ci 341362306a36Sopenharmony_ci if (event->status & DEPEVT_STATUS_SHORT && !chain) 341462306a36Sopenharmony_ci return 1; 341562306a36Sopenharmony_ci 341662306a36Sopenharmony_ci if ((trb->ctrl & DWC3_TRB_CTRL_ISP_IMI) && 341762306a36Sopenharmony_ci DWC3_TRB_SIZE_TRBSTS(trb->size) == DWC3_TRBSTS_MISSED_ISOC) 341862306a36Sopenharmony_ci return 1; 341962306a36Sopenharmony_ci 342062306a36Sopenharmony_ci if ((trb->ctrl & DWC3_TRB_CTRL_IOC) || 342162306a36Sopenharmony_ci (trb->ctrl & DWC3_TRB_CTRL_LST)) 342262306a36Sopenharmony_ci return 1; 342362306a36Sopenharmony_ci 342462306a36Sopenharmony_ci return 0; 342562306a36Sopenharmony_ci} 342662306a36Sopenharmony_ci 342762306a36Sopenharmony_cistatic int dwc3_gadget_ep_reclaim_trb_sg(struct dwc3_ep *dep, 342862306a36Sopenharmony_ci struct dwc3_request *req, const struct dwc3_event_depevt *event, 342962306a36Sopenharmony_ci int status) 343062306a36Sopenharmony_ci{ 343162306a36Sopenharmony_ci struct dwc3_trb *trb = &dep->trb_pool[dep->trb_dequeue]; 343262306a36Sopenharmony_ci struct scatterlist *sg = req->sg; 343362306a36Sopenharmony_ci struct scatterlist *s; 343462306a36Sopenharmony_ci unsigned int num_queued = req->num_queued_sgs; 343562306a36Sopenharmony_ci unsigned int i; 343662306a36Sopenharmony_ci int ret = 0; 343762306a36Sopenharmony_ci 343862306a36Sopenharmony_ci for_each_sg(sg, s, num_queued, i) { 343962306a36Sopenharmony_ci trb = &dep->trb_pool[dep->trb_dequeue]; 344062306a36Sopenharmony_ci 344162306a36Sopenharmony_ci req->sg = sg_next(s); 344262306a36Sopenharmony_ci req->num_queued_sgs--; 344362306a36Sopenharmony_ci 344462306a36Sopenharmony_ci ret = dwc3_gadget_ep_reclaim_completed_trb(dep, req, 344562306a36Sopenharmony_ci trb, event, status, true); 344662306a36Sopenharmony_ci if (ret) 344762306a36Sopenharmony_ci break; 344862306a36Sopenharmony_ci } 344962306a36Sopenharmony_ci 345062306a36Sopenharmony_ci return ret; 345162306a36Sopenharmony_ci} 345262306a36Sopenharmony_ci 345362306a36Sopenharmony_cistatic int dwc3_gadget_ep_reclaim_trb_linear(struct dwc3_ep *dep, 345462306a36Sopenharmony_ci struct dwc3_request *req, const struct dwc3_event_depevt *event, 345562306a36Sopenharmony_ci int status) 345662306a36Sopenharmony_ci{ 345762306a36Sopenharmony_ci struct dwc3_trb *trb = &dep->trb_pool[dep->trb_dequeue]; 345862306a36Sopenharmony_ci 345962306a36Sopenharmony_ci return dwc3_gadget_ep_reclaim_completed_trb(dep, req, trb, 346062306a36Sopenharmony_ci event, status, false); 346162306a36Sopenharmony_ci} 346262306a36Sopenharmony_ci 346362306a36Sopenharmony_cistatic bool dwc3_gadget_ep_request_completed(struct dwc3_request *req) 346462306a36Sopenharmony_ci{ 346562306a36Sopenharmony_ci return req->num_pending_sgs == 0 && req->num_queued_sgs == 0; 346662306a36Sopenharmony_ci} 346762306a36Sopenharmony_ci 346862306a36Sopenharmony_cistatic int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep, 346962306a36Sopenharmony_ci const struct dwc3_event_depevt *event, 347062306a36Sopenharmony_ci struct dwc3_request *req, int status) 347162306a36Sopenharmony_ci{ 347262306a36Sopenharmony_ci int request_status; 347362306a36Sopenharmony_ci int ret; 347462306a36Sopenharmony_ci 347562306a36Sopenharmony_ci if (req->request.num_mapped_sgs) 347662306a36Sopenharmony_ci ret = dwc3_gadget_ep_reclaim_trb_sg(dep, req, event, 347762306a36Sopenharmony_ci status); 347862306a36Sopenharmony_ci else 347962306a36Sopenharmony_ci ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event, 348062306a36Sopenharmony_ci status); 348162306a36Sopenharmony_ci 348262306a36Sopenharmony_ci req->request.actual = req->request.length - req->remaining; 348362306a36Sopenharmony_ci 348462306a36Sopenharmony_ci if (!dwc3_gadget_ep_request_completed(req)) 348562306a36Sopenharmony_ci goto out; 348662306a36Sopenharmony_ci 348762306a36Sopenharmony_ci if (req->needs_extra_trb) { 348862306a36Sopenharmony_ci ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event, 348962306a36Sopenharmony_ci status); 349062306a36Sopenharmony_ci req->needs_extra_trb = false; 349162306a36Sopenharmony_ci } 349262306a36Sopenharmony_ci 349362306a36Sopenharmony_ci /* 349462306a36Sopenharmony_ci * The event status only reflects the status of the TRB with IOC set. 349562306a36Sopenharmony_ci * For the requests that don't set interrupt on completion, the driver 349662306a36Sopenharmony_ci * needs to check and return the status of the completed TRBs associated 349762306a36Sopenharmony_ci * with the request. Use the status of the last TRB of the request. 349862306a36Sopenharmony_ci */ 349962306a36Sopenharmony_ci if (req->request.no_interrupt) { 350062306a36Sopenharmony_ci struct dwc3_trb *trb; 350162306a36Sopenharmony_ci 350262306a36Sopenharmony_ci trb = dwc3_ep_prev_trb(dep, dep->trb_dequeue); 350362306a36Sopenharmony_ci switch (DWC3_TRB_SIZE_TRBSTS(trb->size)) { 350462306a36Sopenharmony_ci case DWC3_TRBSTS_MISSED_ISOC: 350562306a36Sopenharmony_ci /* Isoc endpoint only */ 350662306a36Sopenharmony_ci request_status = -EXDEV; 350762306a36Sopenharmony_ci break; 350862306a36Sopenharmony_ci case DWC3_TRB_STS_XFER_IN_PROG: 350962306a36Sopenharmony_ci /* Applicable when End Transfer with ForceRM=0 */ 351062306a36Sopenharmony_ci case DWC3_TRBSTS_SETUP_PENDING: 351162306a36Sopenharmony_ci /* Control endpoint only */ 351262306a36Sopenharmony_ci case DWC3_TRBSTS_OK: 351362306a36Sopenharmony_ci default: 351462306a36Sopenharmony_ci request_status = 0; 351562306a36Sopenharmony_ci break; 351662306a36Sopenharmony_ci } 351762306a36Sopenharmony_ci } else { 351862306a36Sopenharmony_ci request_status = status; 351962306a36Sopenharmony_ci } 352062306a36Sopenharmony_ci 352162306a36Sopenharmony_ci dwc3_gadget_giveback(dep, req, request_status); 352262306a36Sopenharmony_ci 352362306a36Sopenharmony_ciout: 352462306a36Sopenharmony_ci return ret; 352562306a36Sopenharmony_ci} 352662306a36Sopenharmony_ci 352762306a36Sopenharmony_cistatic void dwc3_gadget_ep_cleanup_completed_requests(struct dwc3_ep *dep, 352862306a36Sopenharmony_ci const struct dwc3_event_depevt *event, int status) 352962306a36Sopenharmony_ci{ 353062306a36Sopenharmony_ci struct dwc3_request *req; 353162306a36Sopenharmony_ci 353262306a36Sopenharmony_ci while (!list_empty(&dep->started_list)) { 353362306a36Sopenharmony_ci int ret; 353462306a36Sopenharmony_ci 353562306a36Sopenharmony_ci req = next_request(&dep->started_list); 353662306a36Sopenharmony_ci ret = dwc3_gadget_ep_cleanup_completed_request(dep, event, 353762306a36Sopenharmony_ci req, status); 353862306a36Sopenharmony_ci if (ret) 353962306a36Sopenharmony_ci break; 354062306a36Sopenharmony_ci /* 354162306a36Sopenharmony_ci * The endpoint is disabled, let the dwc3_remove_requests() 354262306a36Sopenharmony_ci * handle the cleanup. 354362306a36Sopenharmony_ci */ 354462306a36Sopenharmony_ci if (!dep->endpoint.desc) 354562306a36Sopenharmony_ci break; 354662306a36Sopenharmony_ci } 354762306a36Sopenharmony_ci} 354862306a36Sopenharmony_ci 354962306a36Sopenharmony_cistatic bool dwc3_gadget_ep_should_continue(struct dwc3_ep *dep) 355062306a36Sopenharmony_ci{ 355162306a36Sopenharmony_ci struct dwc3_request *req; 355262306a36Sopenharmony_ci struct dwc3 *dwc = dep->dwc; 355362306a36Sopenharmony_ci 355462306a36Sopenharmony_ci if (!dep->endpoint.desc || !dwc->pullups_connected || 355562306a36Sopenharmony_ci !dwc->connected) 355662306a36Sopenharmony_ci return false; 355762306a36Sopenharmony_ci 355862306a36Sopenharmony_ci if (!list_empty(&dep->pending_list)) 355962306a36Sopenharmony_ci return true; 356062306a36Sopenharmony_ci 356162306a36Sopenharmony_ci /* 356262306a36Sopenharmony_ci * We only need to check the first entry of the started list. We can 356362306a36Sopenharmony_ci * assume the completed requests are removed from the started list. 356462306a36Sopenharmony_ci */ 356562306a36Sopenharmony_ci req = next_request(&dep->started_list); 356662306a36Sopenharmony_ci if (!req) 356762306a36Sopenharmony_ci return false; 356862306a36Sopenharmony_ci 356962306a36Sopenharmony_ci return !dwc3_gadget_ep_request_completed(req); 357062306a36Sopenharmony_ci} 357162306a36Sopenharmony_ci 357262306a36Sopenharmony_cistatic void dwc3_gadget_endpoint_frame_from_event(struct dwc3_ep *dep, 357362306a36Sopenharmony_ci const struct dwc3_event_depevt *event) 357462306a36Sopenharmony_ci{ 357562306a36Sopenharmony_ci dep->frame_number = event->parameters; 357662306a36Sopenharmony_ci} 357762306a36Sopenharmony_ci 357862306a36Sopenharmony_cistatic bool dwc3_gadget_endpoint_trbs_complete(struct dwc3_ep *dep, 357962306a36Sopenharmony_ci const struct dwc3_event_depevt *event, int status) 358062306a36Sopenharmony_ci{ 358162306a36Sopenharmony_ci struct dwc3 *dwc = dep->dwc; 358262306a36Sopenharmony_ci bool no_started_trb = true; 358362306a36Sopenharmony_ci 358462306a36Sopenharmony_ci dwc3_gadget_ep_cleanup_completed_requests(dep, event, status); 358562306a36Sopenharmony_ci 358662306a36Sopenharmony_ci if (dep->flags & DWC3_EP_END_TRANSFER_PENDING) 358762306a36Sopenharmony_ci goto out; 358862306a36Sopenharmony_ci 358962306a36Sopenharmony_ci if (!dep->endpoint.desc) 359062306a36Sopenharmony_ci return no_started_trb; 359162306a36Sopenharmony_ci 359262306a36Sopenharmony_ci if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && 359362306a36Sopenharmony_ci list_empty(&dep->started_list) && 359462306a36Sopenharmony_ci (list_empty(&dep->pending_list) || status == -EXDEV)) 359562306a36Sopenharmony_ci dwc3_stop_active_transfer(dep, true, true); 359662306a36Sopenharmony_ci else if (dwc3_gadget_ep_should_continue(dep)) 359762306a36Sopenharmony_ci if (__dwc3_gadget_kick_transfer(dep) == 0) 359862306a36Sopenharmony_ci no_started_trb = false; 359962306a36Sopenharmony_ci 360062306a36Sopenharmony_ciout: 360162306a36Sopenharmony_ci /* 360262306a36Sopenharmony_ci * WORKAROUND: This is the 2nd half of U1/U2 -> U0 workaround. 360362306a36Sopenharmony_ci * See dwc3_gadget_linksts_change_interrupt() for 1st half. 360462306a36Sopenharmony_ci */ 360562306a36Sopenharmony_ci if (DWC3_VER_IS_PRIOR(DWC3, 183A)) { 360662306a36Sopenharmony_ci u32 reg; 360762306a36Sopenharmony_ci int i; 360862306a36Sopenharmony_ci 360962306a36Sopenharmony_ci for (i = 0; i < DWC3_ENDPOINTS_NUM; i++) { 361062306a36Sopenharmony_ci dep = dwc->eps[i]; 361162306a36Sopenharmony_ci 361262306a36Sopenharmony_ci if (!(dep->flags & DWC3_EP_ENABLED)) 361362306a36Sopenharmony_ci continue; 361462306a36Sopenharmony_ci 361562306a36Sopenharmony_ci if (!list_empty(&dep->started_list)) 361662306a36Sopenharmony_ci return no_started_trb; 361762306a36Sopenharmony_ci } 361862306a36Sopenharmony_ci 361962306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_DCTL); 362062306a36Sopenharmony_ci reg |= dwc->u1u2; 362162306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_DCTL, reg); 362262306a36Sopenharmony_ci 362362306a36Sopenharmony_ci dwc->u1u2 = 0; 362462306a36Sopenharmony_ci } 362562306a36Sopenharmony_ci 362662306a36Sopenharmony_ci return no_started_trb; 362762306a36Sopenharmony_ci} 362862306a36Sopenharmony_ci 362962306a36Sopenharmony_cistatic void dwc3_gadget_endpoint_transfer_in_progress(struct dwc3_ep *dep, 363062306a36Sopenharmony_ci const struct dwc3_event_depevt *event) 363162306a36Sopenharmony_ci{ 363262306a36Sopenharmony_ci int status = 0; 363362306a36Sopenharmony_ci 363462306a36Sopenharmony_ci if (!dep->endpoint.desc) 363562306a36Sopenharmony_ci return; 363662306a36Sopenharmony_ci 363762306a36Sopenharmony_ci if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) 363862306a36Sopenharmony_ci dwc3_gadget_endpoint_frame_from_event(dep, event); 363962306a36Sopenharmony_ci 364062306a36Sopenharmony_ci if (event->status & DEPEVT_STATUS_BUSERR) 364162306a36Sopenharmony_ci status = -ECONNRESET; 364262306a36Sopenharmony_ci 364362306a36Sopenharmony_ci if (event->status & DEPEVT_STATUS_MISSED_ISOC) 364462306a36Sopenharmony_ci status = -EXDEV; 364562306a36Sopenharmony_ci 364662306a36Sopenharmony_ci dwc3_gadget_endpoint_trbs_complete(dep, event, status); 364762306a36Sopenharmony_ci} 364862306a36Sopenharmony_ci 364962306a36Sopenharmony_cistatic void dwc3_gadget_endpoint_transfer_complete(struct dwc3_ep *dep, 365062306a36Sopenharmony_ci const struct dwc3_event_depevt *event) 365162306a36Sopenharmony_ci{ 365262306a36Sopenharmony_ci int status = 0; 365362306a36Sopenharmony_ci 365462306a36Sopenharmony_ci dep->flags &= ~DWC3_EP_TRANSFER_STARTED; 365562306a36Sopenharmony_ci 365662306a36Sopenharmony_ci if (event->status & DEPEVT_STATUS_BUSERR) 365762306a36Sopenharmony_ci status = -ECONNRESET; 365862306a36Sopenharmony_ci 365962306a36Sopenharmony_ci if (dwc3_gadget_endpoint_trbs_complete(dep, event, status)) 366062306a36Sopenharmony_ci dep->flags &= ~DWC3_EP_WAIT_TRANSFER_COMPLETE; 366162306a36Sopenharmony_ci} 366262306a36Sopenharmony_ci 366362306a36Sopenharmony_cistatic void dwc3_gadget_endpoint_transfer_not_ready(struct dwc3_ep *dep, 366462306a36Sopenharmony_ci const struct dwc3_event_depevt *event) 366562306a36Sopenharmony_ci{ 366662306a36Sopenharmony_ci dwc3_gadget_endpoint_frame_from_event(dep, event); 366762306a36Sopenharmony_ci 366862306a36Sopenharmony_ci /* 366962306a36Sopenharmony_ci * The XferNotReady event is generated only once before the endpoint 367062306a36Sopenharmony_ci * starts. It will be generated again when END_TRANSFER command is 367162306a36Sopenharmony_ci * issued. For some controller versions, the XferNotReady event may be 367262306a36Sopenharmony_ci * generated while the END_TRANSFER command is still in process. Ignore 367362306a36Sopenharmony_ci * it and wait for the next XferNotReady event after the command is 367462306a36Sopenharmony_ci * completed. 367562306a36Sopenharmony_ci */ 367662306a36Sopenharmony_ci if (dep->flags & DWC3_EP_END_TRANSFER_PENDING) 367762306a36Sopenharmony_ci return; 367862306a36Sopenharmony_ci 367962306a36Sopenharmony_ci (void) __dwc3_gadget_start_isoc(dep); 368062306a36Sopenharmony_ci} 368162306a36Sopenharmony_ci 368262306a36Sopenharmony_cistatic void dwc3_gadget_endpoint_command_complete(struct dwc3_ep *dep, 368362306a36Sopenharmony_ci const struct dwc3_event_depevt *event) 368462306a36Sopenharmony_ci{ 368562306a36Sopenharmony_ci u8 cmd = DEPEVT_PARAMETER_CMD(event->parameters); 368662306a36Sopenharmony_ci 368762306a36Sopenharmony_ci if (cmd != DWC3_DEPCMD_ENDTRANSFER) 368862306a36Sopenharmony_ci return; 368962306a36Sopenharmony_ci 369062306a36Sopenharmony_ci /* 369162306a36Sopenharmony_ci * The END_TRANSFER command will cause the controller to generate a 369262306a36Sopenharmony_ci * NoStream Event, and it's not due to the host DP NoStream rejection. 369362306a36Sopenharmony_ci * Ignore the next NoStream event. 369462306a36Sopenharmony_ci */ 369562306a36Sopenharmony_ci if (dep->stream_capable) 369662306a36Sopenharmony_ci dep->flags |= DWC3_EP_IGNORE_NEXT_NOSTREAM; 369762306a36Sopenharmony_ci 369862306a36Sopenharmony_ci dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING; 369962306a36Sopenharmony_ci dep->flags &= ~DWC3_EP_TRANSFER_STARTED; 370062306a36Sopenharmony_ci dwc3_gadget_ep_cleanup_cancelled_requests(dep); 370162306a36Sopenharmony_ci 370262306a36Sopenharmony_ci if (dep->flags & DWC3_EP_PENDING_CLEAR_STALL) { 370362306a36Sopenharmony_ci struct dwc3 *dwc = dep->dwc; 370462306a36Sopenharmony_ci 370562306a36Sopenharmony_ci dep->flags &= ~DWC3_EP_PENDING_CLEAR_STALL; 370662306a36Sopenharmony_ci if (dwc3_send_clear_stall_ep_cmd(dep)) { 370762306a36Sopenharmony_ci struct usb_ep *ep0 = &dwc->eps[0]->endpoint; 370862306a36Sopenharmony_ci 370962306a36Sopenharmony_ci dev_err(dwc->dev, "failed to clear STALL on %s\n", dep->name); 371062306a36Sopenharmony_ci if (dwc->delayed_status) 371162306a36Sopenharmony_ci __dwc3_gadget_ep0_set_halt(ep0, 1); 371262306a36Sopenharmony_ci return; 371362306a36Sopenharmony_ci } 371462306a36Sopenharmony_ci 371562306a36Sopenharmony_ci dep->flags &= ~(DWC3_EP_STALL | DWC3_EP_WEDGE); 371662306a36Sopenharmony_ci if (dwc->clear_stall_protocol == dep->number) 371762306a36Sopenharmony_ci dwc3_ep0_send_delayed_status(dwc); 371862306a36Sopenharmony_ci } 371962306a36Sopenharmony_ci 372062306a36Sopenharmony_ci if ((dep->flags & DWC3_EP_DELAY_START) && 372162306a36Sopenharmony_ci !usb_endpoint_xfer_isoc(dep->endpoint.desc)) 372262306a36Sopenharmony_ci __dwc3_gadget_kick_transfer(dep); 372362306a36Sopenharmony_ci 372462306a36Sopenharmony_ci dep->flags &= ~DWC3_EP_DELAY_START; 372562306a36Sopenharmony_ci} 372662306a36Sopenharmony_ci 372762306a36Sopenharmony_cistatic void dwc3_gadget_endpoint_stream_event(struct dwc3_ep *dep, 372862306a36Sopenharmony_ci const struct dwc3_event_depevt *event) 372962306a36Sopenharmony_ci{ 373062306a36Sopenharmony_ci struct dwc3 *dwc = dep->dwc; 373162306a36Sopenharmony_ci 373262306a36Sopenharmony_ci if (event->status == DEPEVT_STREAMEVT_FOUND) { 373362306a36Sopenharmony_ci dep->flags |= DWC3_EP_FIRST_STREAM_PRIMED; 373462306a36Sopenharmony_ci goto out; 373562306a36Sopenharmony_ci } 373662306a36Sopenharmony_ci 373762306a36Sopenharmony_ci /* Note: NoStream rejection event param value is 0 and not 0xFFFF */ 373862306a36Sopenharmony_ci switch (event->parameters) { 373962306a36Sopenharmony_ci case DEPEVT_STREAM_PRIME: 374062306a36Sopenharmony_ci /* 374162306a36Sopenharmony_ci * If the host can properly transition the endpoint state from 374262306a36Sopenharmony_ci * idle to prime after a NoStream rejection, there's no need to 374362306a36Sopenharmony_ci * force restarting the endpoint to reinitiate the stream. To 374462306a36Sopenharmony_ci * simplify the check, assume the host follows the USB spec if 374562306a36Sopenharmony_ci * it primed the endpoint more than once. 374662306a36Sopenharmony_ci */ 374762306a36Sopenharmony_ci if (dep->flags & DWC3_EP_FORCE_RESTART_STREAM) { 374862306a36Sopenharmony_ci if (dep->flags & DWC3_EP_FIRST_STREAM_PRIMED) 374962306a36Sopenharmony_ci dep->flags &= ~DWC3_EP_FORCE_RESTART_STREAM; 375062306a36Sopenharmony_ci else 375162306a36Sopenharmony_ci dep->flags |= DWC3_EP_FIRST_STREAM_PRIMED; 375262306a36Sopenharmony_ci } 375362306a36Sopenharmony_ci 375462306a36Sopenharmony_ci break; 375562306a36Sopenharmony_ci case DEPEVT_STREAM_NOSTREAM: 375662306a36Sopenharmony_ci if ((dep->flags & DWC3_EP_IGNORE_NEXT_NOSTREAM) || 375762306a36Sopenharmony_ci !(dep->flags & DWC3_EP_FORCE_RESTART_STREAM) || 375862306a36Sopenharmony_ci (!DWC3_MST_CAPABLE(&dwc->hwparams) && 375962306a36Sopenharmony_ci !(dep->flags & DWC3_EP_WAIT_TRANSFER_COMPLETE))) 376062306a36Sopenharmony_ci break; 376162306a36Sopenharmony_ci 376262306a36Sopenharmony_ci /* 376362306a36Sopenharmony_ci * If the host rejects a stream due to no active stream, by the 376462306a36Sopenharmony_ci * USB and xHCI spec, the endpoint will be put back to idle 376562306a36Sopenharmony_ci * state. When the host is ready (buffer added/updated), it will 376662306a36Sopenharmony_ci * prime the endpoint to inform the usb device controller. This 376762306a36Sopenharmony_ci * triggers the device controller to issue ERDY to restart the 376862306a36Sopenharmony_ci * stream. However, some hosts don't follow this and keep the 376962306a36Sopenharmony_ci * endpoint in the idle state. No prime will come despite host 377062306a36Sopenharmony_ci * streams are updated, and the device controller will not be 377162306a36Sopenharmony_ci * triggered to generate ERDY to move the next stream data. To 377262306a36Sopenharmony_ci * workaround this and maintain compatibility with various 377362306a36Sopenharmony_ci * hosts, force to reinitiate the stream until the host is ready 377462306a36Sopenharmony_ci * instead of waiting for the host to prime the endpoint. 377562306a36Sopenharmony_ci */ 377662306a36Sopenharmony_ci if (DWC3_VER_IS_WITHIN(DWC32, 100A, ANY)) { 377762306a36Sopenharmony_ci unsigned int cmd = DWC3_DGCMD_SET_ENDPOINT_PRIME; 377862306a36Sopenharmony_ci 377962306a36Sopenharmony_ci dwc3_send_gadget_generic_command(dwc, cmd, dep->number); 378062306a36Sopenharmony_ci } else { 378162306a36Sopenharmony_ci dep->flags |= DWC3_EP_DELAY_START; 378262306a36Sopenharmony_ci dwc3_stop_active_transfer(dep, true, true); 378362306a36Sopenharmony_ci return; 378462306a36Sopenharmony_ci } 378562306a36Sopenharmony_ci break; 378662306a36Sopenharmony_ci } 378762306a36Sopenharmony_ci 378862306a36Sopenharmony_ciout: 378962306a36Sopenharmony_ci dep->flags &= ~DWC3_EP_IGNORE_NEXT_NOSTREAM; 379062306a36Sopenharmony_ci} 379162306a36Sopenharmony_ci 379262306a36Sopenharmony_cistatic void dwc3_endpoint_interrupt(struct dwc3 *dwc, 379362306a36Sopenharmony_ci const struct dwc3_event_depevt *event) 379462306a36Sopenharmony_ci{ 379562306a36Sopenharmony_ci struct dwc3_ep *dep; 379662306a36Sopenharmony_ci u8 epnum = event->endpoint_number; 379762306a36Sopenharmony_ci 379862306a36Sopenharmony_ci dep = dwc->eps[epnum]; 379962306a36Sopenharmony_ci 380062306a36Sopenharmony_ci if (!(dep->flags & DWC3_EP_ENABLED)) { 380162306a36Sopenharmony_ci if ((epnum > 1) && !(dep->flags & DWC3_EP_TRANSFER_STARTED)) 380262306a36Sopenharmony_ci return; 380362306a36Sopenharmony_ci 380462306a36Sopenharmony_ci /* Handle only EPCMDCMPLT when EP disabled */ 380562306a36Sopenharmony_ci if ((event->endpoint_event != DWC3_DEPEVT_EPCMDCMPLT) && 380662306a36Sopenharmony_ci !(epnum <= 1 && event->endpoint_event == DWC3_DEPEVT_XFERCOMPLETE)) 380762306a36Sopenharmony_ci return; 380862306a36Sopenharmony_ci } 380962306a36Sopenharmony_ci 381062306a36Sopenharmony_ci if (epnum == 0 || epnum == 1) { 381162306a36Sopenharmony_ci dwc3_ep0_interrupt(dwc, event); 381262306a36Sopenharmony_ci return; 381362306a36Sopenharmony_ci } 381462306a36Sopenharmony_ci 381562306a36Sopenharmony_ci switch (event->endpoint_event) { 381662306a36Sopenharmony_ci case DWC3_DEPEVT_XFERINPROGRESS: 381762306a36Sopenharmony_ci dwc3_gadget_endpoint_transfer_in_progress(dep, event); 381862306a36Sopenharmony_ci break; 381962306a36Sopenharmony_ci case DWC3_DEPEVT_XFERNOTREADY: 382062306a36Sopenharmony_ci dwc3_gadget_endpoint_transfer_not_ready(dep, event); 382162306a36Sopenharmony_ci break; 382262306a36Sopenharmony_ci case DWC3_DEPEVT_EPCMDCMPLT: 382362306a36Sopenharmony_ci dwc3_gadget_endpoint_command_complete(dep, event); 382462306a36Sopenharmony_ci break; 382562306a36Sopenharmony_ci case DWC3_DEPEVT_XFERCOMPLETE: 382662306a36Sopenharmony_ci dwc3_gadget_endpoint_transfer_complete(dep, event); 382762306a36Sopenharmony_ci break; 382862306a36Sopenharmony_ci case DWC3_DEPEVT_STREAMEVT: 382962306a36Sopenharmony_ci dwc3_gadget_endpoint_stream_event(dep, event); 383062306a36Sopenharmony_ci break; 383162306a36Sopenharmony_ci case DWC3_DEPEVT_RXTXFIFOEVT: 383262306a36Sopenharmony_ci break; 383362306a36Sopenharmony_ci default: 383462306a36Sopenharmony_ci dev_err(dwc->dev, "unknown endpoint event %d\n", event->endpoint_event); 383562306a36Sopenharmony_ci break; 383662306a36Sopenharmony_ci } 383762306a36Sopenharmony_ci} 383862306a36Sopenharmony_ci 383962306a36Sopenharmony_cistatic void dwc3_disconnect_gadget(struct dwc3 *dwc) 384062306a36Sopenharmony_ci{ 384162306a36Sopenharmony_ci if (dwc->async_callbacks && dwc->gadget_driver->disconnect) { 384262306a36Sopenharmony_ci spin_unlock(&dwc->lock); 384362306a36Sopenharmony_ci dwc->gadget_driver->disconnect(dwc->gadget); 384462306a36Sopenharmony_ci spin_lock(&dwc->lock); 384562306a36Sopenharmony_ci } 384662306a36Sopenharmony_ci} 384762306a36Sopenharmony_ci 384862306a36Sopenharmony_cistatic void dwc3_suspend_gadget(struct dwc3 *dwc) 384962306a36Sopenharmony_ci{ 385062306a36Sopenharmony_ci if (dwc->async_callbacks && dwc->gadget_driver->suspend) { 385162306a36Sopenharmony_ci spin_unlock(&dwc->lock); 385262306a36Sopenharmony_ci dwc->gadget_driver->suspend(dwc->gadget); 385362306a36Sopenharmony_ci spin_lock(&dwc->lock); 385462306a36Sopenharmony_ci } 385562306a36Sopenharmony_ci} 385662306a36Sopenharmony_ci 385762306a36Sopenharmony_cistatic void dwc3_resume_gadget(struct dwc3 *dwc) 385862306a36Sopenharmony_ci{ 385962306a36Sopenharmony_ci if (dwc->async_callbacks && dwc->gadget_driver->resume) { 386062306a36Sopenharmony_ci spin_unlock(&dwc->lock); 386162306a36Sopenharmony_ci dwc->gadget_driver->resume(dwc->gadget); 386262306a36Sopenharmony_ci spin_lock(&dwc->lock); 386362306a36Sopenharmony_ci } 386462306a36Sopenharmony_ci} 386562306a36Sopenharmony_ci 386662306a36Sopenharmony_cistatic void dwc3_reset_gadget(struct dwc3 *dwc) 386762306a36Sopenharmony_ci{ 386862306a36Sopenharmony_ci if (!dwc->gadget_driver) 386962306a36Sopenharmony_ci return; 387062306a36Sopenharmony_ci 387162306a36Sopenharmony_ci if (dwc->async_callbacks && dwc->gadget->speed != USB_SPEED_UNKNOWN) { 387262306a36Sopenharmony_ci spin_unlock(&dwc->lock); 387362306a36Sopenharmony_ci usb_gadget_udc_reset(dwc->gadget, dwc->gadget_driver); 387462306a36Sopenharmony_ci spin_lock(&dwc->lock); 387562306a36Sopenharmony_ci } 387662306a36Sopenharmony_ci} 387762306a36Sopenharmony_ci 387862306a36Sopenharmony_civoid dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, 387962306a36Sopenharmony_ci bool interrupt) 388062306a36Sopenharmony_ci{ 388162306a36Sopenharmony_ci struct dwc3 *dwc = dep->dwc; 388262306a36Sopenharmony_ci 388362306a36Sopenharmony_ci /* 388462306a36Sopenharmony_ci * Only issue End Transfer command to the control endpoint of a started 388562306a36Sopenharmony_ci * Data Phase. Typically we should only do so in error cases such as 388662306a36Sopenharmony_ci * invalid/unexpected direction as described in the control transfer 388762306a36Sopenharmony_ci * flow of the programming guide. 388862306a36Sopenharmony_ci */ 388962306a36Sopenharmony_ci if (dep->number <= 1 && dwc->ep0state != EP0_DATA_PHASE) 389062306a36Sopenharmony_ci return; 389162306a36Sopenharmony_ci 389262306a36Sopenharmony_ci if (interrupt && (dep->flags & DWC3_EP_DELAY_STOP)) 389362306a36Sopenharmony_ci return; 389462306a36Sopenharmony_ci 389562306a36Sopenharmony_ci if (!(dep->flags & DWC3_EP_TRANSFER_STARTED) || 389662306a36Sopenharmony_ci (dep->flags & DWC3_EP_END_TRANSFER_PENDING)) 389762306a36Sopenharmony_ci return; 389862306a36Sopenharmony_ci 389962306a36Sopenharmony_ci /* 390062306a36Sopenharmony_ci * If a Setup packet is received but yet to DMA out, the controller will 390162306a36Sopenharmony_ci * not process the End Transfer command of any endpoint. Polling of its 390262306a36Sopenharmony_ci * DEPCMD.CmdAct may block setting up TRB for Setup packet, causing a 390362306a36Sopenharmony_ci * timeout. Delay issuing the End Transfer command until the Setup TRB is 390462306a36Sopenharmony_ci * prepared. 390562306a36Sopenharmony_ci */ 390662306a36Sopenharmony_ci if (dwc->ep0state != EP0_SETUP_PHASE && !dwc->delayed_status) { 390762306a36Sopenharmony_ci dep->flags |= DWC3_EP_DELAY_STOP; 390862306a36Sopenharmony_ci return; 390962306a36Sopenharmony_ci } 391062306a36Sopenharmony_ci 391162306a36Sopenharmony_ci /* 391262306a36Sopenharmony_ci * NOTICE: We are violating what the Databook says about the 391362306a36Sopenharmony_ci * EndTransfer command. Ideally we would _always_ wait for the 391462306a36Sopenharmony_ci * EndTransfer Command Completion IRQ, but that's causing too 391562306a36Sopenharmony_ci * much trouble synchronizing between us and gadget driver. 391662306a36Sopenharmony_ci * 391762306a36Sopenharmony_ci * We have discussed this with the IP Provider and it was 391862306a36Sopenharmony_ci * suggested to giveback all requests here. 391962306a36Sopenharmony_ci * 392062306a36Sopenharmony_ci * Note also that a similar handling was tested by Synopsys 392162306a36Sopenharmony_ci * (thanks a lot Paul) and nothing bad has come out of it. 392262306a36Sopenharmony_ci * In short, what we're doing is issuing EndTransfer with 392362306a36Sopenharmony_ci * CMDIOC bit set and delay kicking transfer until the 392462306a36Sopenharmony_ci * EndTransfer command had completed. 392562306a36Sopenharmony_ci * 392662306a36Sopenharmony_ci * As of IP version 3.10a of the DWC_usb3 IP, the controller 392762306a36Sopenharmony_ci * supports a mode to work around the above limitation. The 392862306a36Sopenharmony_ci * software can poll the CMDACT bit in the DEPCMD register 392962306a36Sopenharmony_ci * after issuing a EndTransfer command. This mode is enabled 393062306a36Sopenharmony_ci * by writing GUCTL2[14]. This polling is already done in the 393162306a36Sopenharmony_ci * dwc3_send_gadget_ep_cmd() function so if the mode is 393262306a36Sopenharmony_ci * enabled, the EndTransfer command will have completed upon 393362306a36Sopenharmony_ci * returning from this function. 393462306a36Sopenharmony_ci * 393562306a36Sopenharmony_ci * This mode is NOT available on the DWC_usb31 IP. In this 393662306a36Sopenharmony_ci * case, if the IOC bit is not set, then delay by 1ms 393762306a36Sopenharmony_ci * after issuing the EndTransfer command. This allows for the 393862306a36Sopenharmony_ci * controller to handle the command completely before DWC3 393962306a36Sopenharmony_ci * remove requests attempts to unmap USB request buffers. 394062306a36Sopenharmony_ci */ 394162306a36Sopenharmony_ci 394262306a36Sopenharmony_ci __dwc3_stop_active_transfer(dep, force, interrupt); 394362306a36Sopenharmony_ci} 394462306a36Sopenharmony_ci 394562306a36Sopenharmony_cistatic void dwc3_clear_stall_all_ep(struct dwc3 *dwc) 394662306a36Sopenharmony_ci{ 394762306a36Sopenharmony_ci u32 epnum; 394862306a36Sopenharmony_ci 394962306a36Sopenharmony_ci for (epnum = 1; epnum < DWC3_ENDPOINTS_NUM; epnum++) { 395062306a36Sopenharmony_ci struct dwc3_ep *dep; 395162306a36Sopenharmony_ci int ret; 395262306a36Sopenharmony_ci 395362306a36Sopenharmony_ci dep = dwc->eps[epnum]; 395462306a36Sopenharmony_ci if (!dep) 395562306a36Sopenharmony_ci continue; 395662306a36Sopenharmony_ci 395762306a36Sopenharmony_ci if (!(dep->flags & DWC3_EP_STALL)) 395862306a36Sopenharmony_ci continue; 395962306a36Sopenharmony_ci 396062306a36Sopenharmony_ci dep->flags &= ~DWC3_EP_STALL; 396162306a36Sopenharmony_ci 396262306a36Sopenharmony_ci ret = dwc3_send_clear_stall_ep_cmd(dep); 396362306a36Sopenharmony_ci WARN_ON_ONCE(ret); 396462306a36Sopenharmony_ci } 396562306a36Sopenharmony_ci} 396662306a36Sopenharmony_ci 396762306a36Sopenharmony_cistatic void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc) 396862306a36Sopenharmony_ci{ 396962306a36Sopenharmony_ci int reg; 397062306a36Sopenharmony_ci 397162306a36Sopenharmony_ci dwc->suspended = false; 397262306a36Sopenharmony_ci 397362306a36Sopenharmony_ci dwc3_gadget_set_link_state(dwc, DWC3_LINK_STATE_RX_DET); 397462306a36Sopenharmony_ci 397562306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_DCTL); 397662306a36Sopenharmony_ci reg &= ~DWC3_DCTL_INITU1ENA; 397762306a36Sopenharmony_ci reg &= ~DWC3_DCTL_INITU2ENA; 397862306a36Sopenharmony_ci dwc3_gadget_dctl_write_safe(dwc, reg); 397962306a36Sopenharmony_ci 398062306a36Sopenharmony_ci dwc->connected = false; 398162306a36Sopenharmony_ci 398262306a36Sopenharmony_ci dwc3_disconnect_gadget(dwc); 398362306a36Sopenharmony_ci 398462306a36Sopenharmony_ci dwc->gadget->speed = USB_SPEED_UNKNOWN; 398562306a36Sopenharmony_ci dwc->setup_packet_pending = false; 398662306a36Sopenharmony_ci dwc->gadget->wakeup_armed = false; 398762306a36Sopenharmony_ci dwc3_gadget_enable_linksts_evts(dwc, false); 398862306a36Sopenharmony_ci usb_gadget_set_state(dwc->gadget, USB_STATE_NOTATTACHED); 398962306a36Sopenharmony_ci 399062306a36Sopenharmony_ci dwc3_ep0_reset_state(dwc); 399162306a36Sopenharmony_ci 399262306a36Sopenharmony_ci /* 399362306a36Sopenharmony_ci * Request PM idle to address condition where usage count is 399462306a36Sopenharmony_ci * already decremented to zero, but waiting for the disconnect 399562306a36Sopenharmony_ci * interrupt to set dwc->connected to FALSE. 399662306a36Sopenharmony_ci */ 399762306a36Sopenharmony_ci pm_request_idle(dwc->dev); 399862306a36Sopenharmony_ci} 399962306a36Sopenharmony_ci 400062306a36Sopenharmony_cistatic void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) 400162306a36Sopenharmony_ci{ 400262306a36Sopenharmony_ci u32 reg; 400362306a36Sopenharmony_ci 400462306a36Sopenharmony_ci dwc->suspended = false; 400562306a36Sopenharmony_ci 400662306a36Sopenharmony_ci /* 400762306a36Sopenharmony_ci * Ideally, dwc3_reset_gadget() would trigger the function 400862306a36Sopenharmony_ci * drivers to stop any active transfers through ep disable. 400962306a36Sopenharmony_ci * However, for functions which defer ep disable, such as mass 401062306a36Sopenharmony_ci * storage, we will need to rely on the call to stop active 401162306a36Sopenharmony_ci * transfers here, and avoid allowing of request queuing. 401262306a36Sopenharmony_ci */ 401362306a36Sopenharmony_ci dwc->connected = false; 401462306a36Sopenharmony_ci 401562306a36Sopenharmony_ci /* 401662306a36Sopenharmony_ci * WORKAROUND: DWC3 revisions <1.88a have an issue which 401762306a36Sopenharmony_ci * would cause a missing Disconnect Event if there's a 401862306a36Sopenharmony_ci * pending Setup Packet in the FIFO. 401962306a36Sopenharmony_ci * 402062306a36Sopenharmony_ci * There's no suggested workaround on the official Bug 402162306a36Sopenharmony_ci * report, which states that "unless the driver/application 402262306a36Sopenharmony_ci * is doing any special handling of a disconnect event, 402362306a36Sopenharmony_ci * there is no functional issue". 402462306a36Sopenharmony_ci * 402562306a36Sopenharmony_ci * Unfortunately, it turns out that we _do_ some special 402662306a36Sopenharmony_ci * handling of a disconnect event, namely complete all 402762306a36Sopenharmony_ci * pending transfers, notify gadget driver of the 402862306a36Sopenharmony_ci * disconnection, and so on. 402962306a36Sopenharmony_ci * 403062306a36Sopenharmony_ci * Our suggested workaround is to follow the Disconnect 403162306a36Sopenharmony_ci * Event steps here, instead, based on a setup_packet_pending 403262306a36Sopenharmony_ci * flag. Such flag gets set whenever we have a SETUP_PENDING 403362306a36Sopenharmony_ci * status for EP0 TRBs and gets cleared on XferComplete for the 403462306a36Sopenharmony_ci * same endpoint. 403562306a36Sopenharmony_ci * 403662306a36Sopenharmony_ci * Refers to: 403762306a36Sopenharmony_ci * 403862306a36Sopenharmony_ci * STAR#9000466709: RTL: Device : Disconnect event not 403962306a36Sopenharmony_ci * generated if setup packet pending in FIFO 404062306a36Sopenharmony_ci */ 404162306a36Sopenharmony_ci if (DWC3_VER_IS_PRIOR(DWC3, 188A)) { 404262306a36Sopenharmony_ci if (dwc->setup_packet_pending) 404362306a36Sopenharmony_ci dwc3_gadget_disconnect_interrupt(dwc); 404462306a36Sopenharmony_ci } 404562306a36Sopenharmony_ci 404662306a36Sopenharmony_ci dwc3_reset_gadget(dwc); 404762306a36Sopenharmony_ci 404862306a36Sopenharmony_ci /* 404962306a36Sopenharmony_ci * From SNPS databook section 8.1.2, the EP0 should be in setup 405062306a36Sopenharmony_ci * phase. So ensure that EP0 is in setup phase by issuing a stall 405162306a36Sopenharmony_ci * and restart if EP0 is not in setup phase. 405262306a36Sopenharmony_ci */ 405362306a36Sopenharmony_ci dwc3_ep0_reset_state(dwc); 405462306a36Sopenharmony_ci 405562306a36Sopenharmony_ci /* 405662306a36Sopenharmony_ci * In the Synopsis DesignWare Cores USB3 Databook Rev. 3.30a 405762306a36Sopenharmony_ci * Section 4.1.2 Table 4-2, it states that during a USB reset, the SW 405862306a36Sopenharmony_ci * needs to ensure that it sends "a DEPENDXFER command for any active 405962306a36Sopenharmony_ci * transfers." 406062306a36Sopenharmony_ci */ 406162306a36Sopenharmony_ci dwc3_stop_active_transfers(dwc); 406262306a36Sopenharmony_ci dwc->connected = true; 406362306a36Sopenharmony_ci 406462306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_DCTL); 406562306a36Sopenharmony_ci reg &= ~DWC3_DCTL_TSTCTRL_MASK; 406662306a36Sopenharmony_ci dwc3_gadget_dctl_write_safe(dwc, reg); 406762306a36Sopenharmony_ci dwc->test_mode = false; 406862306a36Sopenharmony_ci dwc->gadget->wakeup_armed = false; 406962306a36Sopenharmony_ci dwc3_gadget_enable_linksts_evts(dwc, false); 407062306a36Sopenharmony_ci dwc3_clear_stall_all_ep(dwc); 407162306a36Sopenharmony_ci 407262306a36Sopenharmony_ci /* Reset device address to zero */ 407362306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_DCFG); 407462306a36Sopenharmony_ci reg &= ~(DWC3_DCFG_DEVADDR_MASK); 407562306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_DCFG, reg); 407662306a36Sopenharmony_ci} 407762306a36Sopenharmony_ci 407862306a36Sopenharmony_cistatic void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) 407962306a36Sopenharmony_ci{ 408062306a36Sopenharmony_ci struct dwc3_ep *dep; 408162306a36Sopenharmony_ci int ret; 408262306a36Sopenharmony_ci u32 reg; 408362306a36Sopenharmony_ci u8 lanes = 1; 408462306a36Sopenharmony_ci u8 speed; 408562306a36Sopenharmony_ci 408662306a36Sopenharmony_ci if (!dwc->softconnect) 408762306a36Sopenharmony_ci return; 408862306a36Sopenharmony_ci 408962306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_DSTS); 409062306a36Sopenharmony_ci speed = reg & DWC3_DSTS_CONNECTSPD; 409162306a36Sopenharmony_ci dwc->speed = speed; 409262306a36Sopenharmony_ci 409362306a36Sopenharmony_ci if (DWC3_IP_IS(DWC32)) 409462306a36Sopenharmony_ci lanes = DWC3_DSTS_CONNLANES(reg) + 1; 409562306a36Sopenharmony_ci 409662306a36Sopenharmony_ci dwc->gadget->ssp_rate = USB_SSP_GEN_UNKNOWN; 409762306a36Sopenharmony_ci 409862306a36Sopenharmony_ci /* 409962306a36Sopenharmony_ci * RAMClkSel is reset to 0 after USB reset, so it must be reprogrammed 410062306a36Sopenharmony_ci * each time on Connect Done. 410162306a36Sopenharmony_ci * 410262306a36Sopenharmony_ci * Currently we always use the reset value. If any platform 410362306a36Sopenharmony_ci * wants to set this to a different value, we need to add a 410462306a36Sopenharmony_ci * setting and update GCTL.RAMCLKSEL here. 410562306a36Sopenharmony_ci */ 410662306a36Sopenharmony_ci 410762306a36Sopenharmony_ci switch (speed) { 410862306a36Sopenharmony_ci case DWC3_DSTS_SUPERSPEED_PLUS: 410962306a36Sopenharmony_ci dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512); 411062306a36Sopenharmony_ci dwc->gadget->ep0->maxpacket = 512; 411162306a36Sopenharmony_ci dwc->gadget->speed = USB_SPEED_SUPER_PLUS; 411262306a36Sopenharmony_ci 411362306a36Sopenharmony_ci if (lanes > 1) 411462306a36Sopenharmony_ci dwc->gadget->ssp_rate = USB_SSP_GEN_2x2; 411562306a36Sopenharmony_ci else 411662306a36Sopenharmony_ci dwc->gadget->ssp_rate = USB_SSP_GEN_2x1; 411762306a36Sopenharmony_ci break; 411862306a36Sopenharmony_ci case DWC3_DSTS_SUPERSPEED: 411962306a36Sopenharmony_ci /* 412062306a36Sopenharmony_ci * WORKAROUND: DWC3 revisions <1.90a have an issue which 412162306a36Sopenharmony_ci * would cause a missing USB3 Reset event. 412262306a36Sopenharmony_ci * 412362306a36Sopenharmony_ci * In such situations, we should force a USB3 Reset 412462306a36Sopenharmony_ci * event by calling our dwc3_gadget_reset_interrupt() 412562306a36Sopenharmony_ci * routine. 412662306a36Sopenharmony_ci * 412762306a36Sopenharmony_ci * Refers to: 412862306a36Sopenharmony_ci * 412962306a36Sopenharmony_ci * STAR#9000483510: RTL: SS : USB3 reset event may 413062306a36Sopenharmony_ci * not be generated always when the link enters poll 413162306a36Sopenharmony_ci */ 413262306a36Sopenharmony_ci if (DWC3_VER_IS_PRIOR(DWC3, 190A)) 413362306a36Sopenharmony_ci dwc3_gadget_reset_interrupt(dwc); 413462306a36Sopenharmony_ci 413562306a36Sopenharmony_ci dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512); 413662306a36Sopenharmony_ci dwc->gadget->ep0->maxpacket = 512; 413762306a36Sopenharmony_ci dwc->gadget->speed = USB_SPEED_SUPER; 413862306a36Sopenharmony_ci 413962306a36Sopenharmony_ci if (lanes > 1) { 414062306a36Sopenharmony_ci dwc->gadget->speed = USB_SPEED_SUPER_PLUS; 414162306a36Sopenharmony_ci dwc->gadget->ssp_rate = USB_SSP_GEN_1x2; 414262306a36Sopenharmony_ci } 414362306a36Sopenharmony_ci break; 414462306a36Sopenharmony_ci case DWC3_DSTS_HIGHSPEED: 414562306a36Sopenharmony_ci dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(64); 414662306a36Sopenharmony_ci dwc->gadget->ep0->maxpacket = 64; 414762306a36Sopenharmony_ci dwc->gadget->speed = USB_SPEED_HIGH; 414862306a36Sopenharmony_ci break; 414962306a36Sopenharmony_ci case DWC3_DSTS_FULLSPEED: 415062306a36Sopenharmony_ci dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(64); 415162306a36Sopenharmony_ci dwc->gadget->ep0->maxpacket = 64; 415262306a36Sopenharmony_ci dwc->gadget->speed = USB_SPEED_FULL; 415362306a36Sopenharmony_ci break; 415462306a36Sopenharmony_ci } 415562306a36Sopenharmony_ci 415662306a36Sopenharmony_ci dwc->eps[1]->endpoint.maxpacket = dwc->gadget->ep0->maxpacket; 415762306a36Sopenharmony_ci 415862306a36Sopenharmony_ci /* Enable USB2 LPM Capability */ 415962306a36Sopenharmony_ci 416062306a36Sopenharmony_ci if (!DWC3_VER_IS_WITHIN(DWC3, ANY, 194A) && 416162306a36Sopenharmony_ci !dwc->usb2_gadget_lpm_disable && 416262306a36Sopenharmony_ci (speed != DWC3_DSTS_SUPERSPEED) && 416362306a36Sopenharmony_ci (speed != DWC3_DSTS_SUPERSPEED_PLUS)) { 416462306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_DCFG); 416562306a36Sopenharmony_ci reg |= DWC3_DCFG_LPM_CAP; 416662306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_DCFG, reg); 416762306a36Sopenharmony_ci 416862306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_DCTL); 416962306a36Sopenharmony_ci reg &= ~(DWC3_DCTL_HIRD_THRES_MASK | DWC3_DCTL_L1_HIBER_EN); 417062306a36Sopenharmony_ci 417162306a36Sopenharmony_ci reg |= DWC3_DCTL_HIRD_THRES(dwc->hird_threshold | 417262306a36Sopenharmony_ci (dwc->is_utmi_l1_suspend << 4)); 417362306a36Sopenharmony_ci 417462306a36Sopenharmony_ci /* 417562306a36Sopenharmony_ci * When dwc3 revisions >= 2.40a, LPM Erratum is enabled and 417662306a36Sopenharmony_ci * DCFG.LPMCap is set, core responses with an ACK and the 417762306a36Sopenharmony_ci * BESL value in the LPM token is less than or equal to LPM 417862306a36Sopenharmony_ci * NYET threshold. 417962306a36Sopenharmony_ci */ 418062306a36Sopenharmony_ci WARN_ONCE(DWC3_VER_IS_PRIOR(DWC3, 240A) && dwc->has_lpm_erratum, 418162306a36Sopenharmony_ci "LPM Erratum not available on dwc3 revisions < 2.40a\n"); 418262306a36Sopenharmony_ci 418362306a36Sopenharmony_ci if (dwc->has_lpm_erratum && !DWC3_VER_IS_PRIOR(DWC3, 240A)) 418462306a36Sopenharmony_ci reg |= DWC3_DCTL_NYET_THRES(dwc->lpm_nyet_threshold); 418562306a36Sopenharmony_ci 418662306a36Sopenharmony_ci dwc3_gadget_dctl_write_safe(dwc, reg); 418762306a36Sopenharmony_ci } else { 418862306a36Sopenharmony_ci if (dwc->usb2_gadget_lpm_disable) { 418962306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_DCFG); 419062306a36Sopenharmony_ci reg &= ~DWC3_DCFG_LPM_CAP; 419162306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_DCFG, reg); 419262306a36Sopenharmony_ci } 419362306a36Sopenharmony_ci 419462306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_DCTL); 419562306a36Sopenharmony_ci reg &= ~DWC3_DCTL_HIRD_THRES_MASK; 419662306a36Sopenharmony_ci dwc3_gadget_dctl_write_safe(dwc, reg); 419762306a36Sopenharmony_ci } 419862306a36Sopenharmony_ci 419962306a36Sopenharmony_ci dep = dwc->eps[0]; 420062306a36Sopenharmony_ci ret = __dwc3_gadget_ep_enable(dep, DWC3_DEPCFG_ACTION_MODIFY); 420162306a36Sopenharmony_ci if (ret) { 420262306a36Sopenharmony_ci dev_err(dwc->dev, "failed to enable %s\n", dep->name); 420362306a36Sopenharmony_ci return; 420462306a36Sopenharmony_ci } 420562306a36Sopenharmony_ci 420662306a36Sopenharmony_ci dep = dwc->eps[1]; 420762306a36Sopenharmony_ci ret = __dwc3_gadget_ep_enable(dep, DWC3_DEPCFG_ACTION_MODIFY); 420862306a36Sopenharmony_ci if (ret) { 420962306a36Sopenharmony_ci dev_err(dwc->dev, "failed to enable %s\n", dep->name); 421062306a36Sopenharmony_ci return; 421162306a36Sopenharmony_ci } 421262306a36Sopenharmony_ci 421362306a36Sopenharmony_ci /* 421462306a36Sopenharmony_ci * Configure PHY via GUSB3PIPECTLn if required. 421562306a36Sopenharmony_ci * 421662306a36Sopenharmony_ci * Update GTXFIFOSIZn 421762306a36Sopenharmony_ci * 421862306a36Sopenharmony_ci * In both cases reset values should be sufficient. 421962306a36Sopenharmony_ci */ 422062306a36Sopenharmony_ci} 422162306a36Sopenharmony_ci 422262306a36Sopenharmony_cistatic void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc, unsigned int evtinfo) 422362306a36Sopenharmony_ci{ 422462306a36Sopenharmony_ci dwc->suspended = false; 422562306a36Sopenharmony_ci 422662306a36Sopenharmony_ci /* 422762306a36Sopenharmony_ci * TODO take core out of low power mode when that's 422862306a36Sopenharmony_ci * implemented. 422962306a36Sopenharmony_ci */ 423062306a36Sopenharmony_ci 423162306a36Sopenharmony_ci if (dwc->async_callbacks && dwc->gadget_driver->resume) { 423262306a36Sopenharmony_ci spin_unlock(&dwc->lock); 423362306a36Sopenharmony_ci dwc->gadget_driver->resume(dwc->gadget); 423462306a36Sopenharmony_ci spin_lock(&dwc->lock); 423562306a36Sopenharmony_ci } 423662306a36Sopenharmony_ci 423762306a36Sopenharmony_ci dwc->link_state = evtinfo & DWC3_LINK_STATE_MASK; 423862306a36Sopenharmony_ci} 423962306a36Sopenharmony_ci 424062306a36Sopenharmony_cistatic void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc, 424162306a36Sopenharmony_ci unsigned int evtinfo) 424262306a36Sopenharmony_ci{ 424362306a36Sopenharmony_ci enum dwc3_link_state next = evtinfo & DWC3_LINK_STATE_MASK; 424462306a36Sopenharmony_ci unsigned int pwropt; 424562306a36Sopenharmony_ci 424662306a36Sopenharmony_ci /* 424762306a36Sopenharmony_ci * WORKAROUND: DWC3 < 2.50a have an issue when configured without 424862306a36Sopenharmony_ci * Hibernation mode enabled which would show up when device detects 424962306a36Sopenharmony_ci * host-initiated U3 exit. 425062306a36Sopenharmony_ci * 425162306a36Sopenharmony_ci * In that case, device will generate a Link State Change Interrupt 425262306a36Sopenharmony_ci * from U3 to RESUME which is only necessary if Hibernation is 425362306a36Sopenharmony_ci * configured in. 425462306a36Sopenharmony_ci * 425562306a36Sopenharmony_ci * There are no functional changes due to such spurious event and we 425662306a36Sopenharmony_ci * just need to ignore it. 425762306a36Sopenharmony_ci * 425862306a36Sopenharmony_ci * Refers to: 425962306a36Sopenharmony_ci * 426062306a36Sopenharmony_ci * STAR#9000570034 RTL: SS Resume event generated in non-Hibernation 426162306a36Sopenharmony_ci * operational mode 426262306a36Sopenharmony_ci */ 426362306a36Sopenharmony_ci pwropt = DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1); 426462306a36Sopenharmony_ci if (DWC3_VER_IS_PRIOR(DWC3, 250A) && 426562306a36Sopenharmony_ci (pwropt != DWC3_GHWPARAMS1_EN_PWROPT_HIB)) { 426662306a36Sopenharmony_ci if ((dwc->link_state == DWC3_LINK_STATE_U3) && 426762306a36Sopenharmony_ci (next == DWC3_LINK_STATE_RESUME)) { 426862306a36Sopenharmony_ci return; 426962306a36Sopenharmony_ci } 427062306a36Sopenharmony_ci } 427162306a36Sopenharmony_ci 427262306a36Sopenharmony_ci /* 427362306a36Sopenharmony_ci * WORKAROUND: DWC3 Revisions <1.83a have an issue which, depending 427462306a36Sopenharmony_ci * on the link partner, the USB session might do multiple entry/exit 427562306a36Sopenharmony_ci * of low power states before a transfer takes place. 427662306a36Sopenharmony_ci * 427762306a36Sopenharmony_ci * Due to this problem, we might experience lower throughput. The 427862306a36Sopenharmony_ci * suggested workaround is to disable DCTL[12:9] bits if we're 427962306a36Sopenharmony_ci * transitioning from U1/U2 to U0 and enable those bits again 428062306a36Sopenharmony_ci * after a transfer completes and there are no pending transfers 428162306a36Sopenharmony_ci * on any of the enabled endpoints. 428262306a36Sopenharmony_ci * 428362306a36Sopenharmony_ci * This is the first half of that workaround. 428462306a36Sopenharmony_ci * 428562306a36Sopenharmony_ci * Refers to: 428662306a36Sopenharmony_ci * 428762306a36Sopenharmony_ci * STAR#9000446952: RTL: Device SS : if U1/U2 ->U0 takes >128us 428862306a36Sopenharmony_ci * core send LGO_Ux entering U0 428962306a36Sopenharmony_ci */ 429062306a36Sopenharmony_ci if (DWC3_VER_IS_PRIOR(DWC3, 183A)) { 429162306a36Sopenharmony_ci if (next == DWC3_LINK_STATE_U0) { 429262306a36Sopenharmony_ci u32 u1u2; 429362306a36Sopenharmony_ci u32 reg; 429462306a36Sopenharmony_ci 429562306a36Sopenharmony_ci switch (dwc->link_state) { 429662306a36Sopenharmony_ci case DWC3_LINK_STATE_U1: 429762306a36Sopenharmony_ci case DWC3_LINK_STATE_U2: 429862306a36Sopenharmony_ci reg = dwc3_readl(dwc->regs, DWC3_DCTL); 429962306a36Sopenharmony_ci u1u2 = reg & (DWC3_DCTL_INITU2ENA 430062306a36Sopenharmony_ci | DWC3_DCTL_ACCEPTU2ENA 430162306a36Sopenharmony_ci | DWC3_DCTL_INITU1ENA 430262306a36Sopenharmony_ci | DWC3_DCTL_ACCEPTU1ENA); 430362306a36Sopenharmony_ci 430462306a36Sopenharmony_ci if (!dwc->u1u2) 430562306a36Sopenharmony_ci dwc->u1u2 = reg & u1u2; 430662306a36Sopenharmony_ci 430762306a36Sopenharmony_ci reg &= ~u1u2; 430862306a36Sopenharmony_ci 430962306a36Sopenharmony_ci dwc3_gadget_dctl_write_safe(dwc, reg); 431062306a36Sopenharmony_ci break; 431162306a36Sopenharmony_ci default: 431262306a36Sopenharmony_ci /* do nothing */ 431362306a36Sopenharmony_ci break; 431462306a36Sopenharmony_ci } 431562306a36Sopenharmony_ci } 431662306a36Sopenharmony_ci } 431762306a36Sopenharmony_ci 431862306a36Sopenharmony_ci switch (next) { 431962306a36Sopenharmony_ci case DWC3_LINK_STATE_U0: 432062306a36Sopenharmony_ci if (dwc->gadget->wakeup_armed) { 432162306a36Sopenharmony_ci dwc3_gadget_enable_linksts_evts(dwc, false); 432262306a36Sopenharmony_ci dwc3_resume_gadget(dwc); 432362306a36Sopenharmony_ci dwc->suspended = false; 432462306a36Sopenharmony_ci } 432562306a36Sopenharmony_ci break; 432662306a36Sopenharmony_ci case DWC3_LINK_STATE_U1: 432762306a36Sopenharmony_ci if (dwc->speed == USB_SPEED_SUPER) 432862306a36Sopenharmony_ci dwc3_suspend_gadget(dwc); 432962306a36Sopenharmony_ci break; 433062306a36Sopenharmony_ci case DWC3_LINK_STATE_U2: 433162306a36Sopenharmony_ci case DWC3_LINK_STATE_U3: 433262306a36Sopenharmony_ci dwc3_suspend_gadget(dwc); 433362306a36Sopenharmony_ci break; 433462306a36Sopenharmony_ci case DWC3_LINK_STATE_RESUME: 433562306a36Sopenharmony_ci dwc3_resume_gadget(dwc); 433662306a36Sopenharmony_ci break; 433762306a36Sopenharmony_ci default: 433862306a36Sopenharmony_ci /* do nothing */ 433962306a36Sopenharmony_ci break; 434062306a36Sopenharmony_ci } 434162306a36Sopenharmony_ci 434262306a36Sopenharmony_ci dwc->link_state = next; 434362306a36Sopenharmony_ci} 434462306a36Sopenharmony_ci 434562306a36Sopenharmony_cistatic void dwc3_gadget_suspend_interrupt(struct dwc3 *dwc, 434662306a36Sopenharmony_ci unsigned int evtinfo) 434762306a36Sopenharmony_ci{ 434862306a36Sopenharmony_ci enum dwc3_link_state next = evtinfo & DWC3_LINK_STATE_MASK; 434962306a36Sopenharmony_ci 435062306a36Sopenharmony_ci if (!dwc->suspended && next == DWC3_LINK_STATE_U3) { 435162306a36Sopenharmony_ci dwc->suspended = true; 435262306a36Sopenharmony_ci dwc3_suspend_gadget(dwc); 435362306a36Sopenharmony_ci } 435462306a36Sopenharmony_ci 435562306a36Sopenharmony_ci dwc->link_state = next; 435662306a36Sopenharmony_ci} 435762306a36Sopenharmony_ci 435862306a36Sopenharmony_cistatic void dwc3_gadget_interrupt(struct dwc3 *dwc, 435962306a36Sopenharmony_ci const struct dwc3_event_devt *event) 436062306a36Sopenharmony_ci{ 436162306a36Sopenharmony_ci switch (event->type) { 436262306a36Sopenharmony_ci case DWC3_DEVICE_EVENT_DISCONNECT: 436362306a36Sopenharmony_ci dwc3_gadget_disconnect_interrupt(dwc); 436462306a36Sopenharmony_ci break; 436562306a36Sopenharmony_ci case DWC3_DEVICE_EVENT_RESET: 436662306a36Sopenharmony_ci dwc3_gadget_reset_interrupt(dwc); 436762306a36Sopenharmony_ci break; 436862306a36Sopenharmony_ci case DWC3_DEVICE_EVENT_CONNECT_DONE: 436962306a36Sopenharmony_ci dwc3_gadget_conndone_interrupt(dwc); 437062306a36Sopenharmony_ci break; 437162306a36Sopenharmony_ci case DWC3_DEVICE_EVENT_WAKEUP: 437262306a36Sopenharmony_ci dwc3_gadget_wakeup_interrupt(dwc, event->event_info); 437362306a36Sopenharmony_ci break; 437462306a36Sopenharmony_ci case DWC3_DEVICE_EVENT_HIBER_REQ: 437562306a36Sopenharmony_ci dev_WARN_ONCE(dwc->dev, true, "unexpected hibernation event\n"); 437662306a36Sopenharmony_ci break; 437762306a36Sopenharmony_ci case DWC3_DEVICE_EVENT_LINK_STATUS_CHANGE: 437862306a36Sopenharmony_ci dwc3_gadget_linksts_change_interrupt(dwc, event->event_info); 437962306a36Sopenharmony_ci break; 438062306a36Sopenharmony_ci case DWC3_DEVICE_EVENT_SUSPEND: 438162306a36Sopenharmony_ci /* It changed to be suspend event for version 2.30a and above */ 438262306a36Sopenharmony_ci if (!DWC3_VER_IS_PRIOR(DWC3, 230A)) 438362306a36Sopenharmony_ci dwc3_gadget_suspend_interrupt(dwc, event->event_info); 438462306a36Sopenharmony_ci break; 438562306a36Sopenharmony_ci case DWC3_DEVICE_EVENT_SOF: 438662306a36Sopenharmony_ci case DWC3_DEVICE_EVENT_ERRATIC_ERROR: 438762306a36Sopenharmony_ci case DWC3_DEVICE_EVENT_CMD_CMPL: 438862306a36Sopenharmony_ci case DWC3_DEVICE_EVENT_OVERFLOW: 438962306a36Sopenharmony_ci break; 439062306a36Sopenharmony_ci default: 439162306a36Sopenharmony_ci dev_WARN(dwc->dev, "UNKNOWN IRQ %d\n", event->type); 439262306a36Sopenharmony_ci } 439362306a36Sopenharmony_ci} 439462306a36Sopenharmony_ci 439562306a36Sopenharmony_cistatic void dwc3_process_event_entry(struct dwc3 *dwc, 439662306a36Sopenharmony_ci const union dwc3_event *event) 439762306a36Sopenharmony_ci{ 439862306a36Sopenharmony_ci trace_dwc3_event(event->raw, dwc); 439962306a36Sopenharmony_ci 440062306a36Sopenharmony_ci if (!event->type.is_devspec) 440162306a36Sopenharmony_ci dwc3_endpoint_interrupt(dwc, &event->depevt); 440262306a36Sopenharmony_ci else if (event->type.type == DWC3_EVENT_TYPE_DEV) 440362306a36Sopenharmony_ci dwc3_gadget_interrupt(dwc, &event->devt); 440462306a36Sopenharmony_ci else 440562306a36Sopenharmony_ci dev_err(dwc->dev, "UNKNOWN IRQ type %d\n", event->raw); 440662306a36Sopenharmony_ci} 440762306a36Sopenharmony_ci 440862306a36Sopenharmony_cistatic irqreturn_t dwc3_process_event_buf(struct dwc3_event_buffer *evt) 440962306a36Sopenharmony_ci{ 441062306a36Sopenharmony_ci struct dwc3 *dwc = evt->dwc; 441162306a36Sopenharmony_ci irqreturn_t ret = IRQ_NONE; 441262306a36Sopenharmony_ci int left; 441362306a36Sopenharmony_ci 441462306a36Sopenharmony_ci left = evt->count; 441562306a36Sopenharmony_ci 441662306a36Sopenharmony_ci if (!(evt->flags & DWC3_EVENT_PENDING)) 441762306a36Sopenharmony_ci return IRQ_NONE; 441862306a36Sopenharmony_ci 441962306a36Sopenharmony_ci while (left > 0) { 442062306a36Sopenharmony_ci union dwc3_event event; 442162306a36Sopenharmony_ci 442262306a36Sopenharmony_ci event.raw = *(u32 *) (evt->cache + evt->lpos); 442362306a36Sopenharmony_ci 442462306a36Sopenharmony_ci dwc3_process_event_entry(dwc, &event); 442562306a36Sopenharmony_ci 442662306a36Sopenharmony_ci /* 442762306a36Sopenharmony_ci * FIXME we wrap around correctly to the next entry as 442862306a36Sopenharmony_ci * almost all entries are 4 bytes in size. There is one 442962306a36Sopenharmony_ci * entry which has 12 bytes which is a regular entry 443062306a36Sopenharmony_ci * followed by 8 bytes data. ATM I don't know how 443162306a36Sopenharmony_ci * things are organized if we get next to the a 443262306a36Sopenharmony_ci * boundary so I worry about that once we try to handle 443362306a36Sopenharmony_ci * that. 443462306a36Sopenharmony_ci */ 443562306a36Sopenharmony_ci evt->lpos = (evt->lpos + 4) % evt->length; 443662306a36Sopenharmony_ci left -= 4; 443762306a36Sopenharmony_ci } 443862306a36Sopenharmony_ci 443962306a36Sopenharmony_ci evt->count = 0; 444062306a36Sopenharmony_ci ret = IRQ_HANDLED; 444162306a36Sopenharmony_ci 444262306a36Sopenharmony_ci /* Unmask interrupt */ 444362306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), 444462306a36Sopenharmony_ci DWC3_GEVNTSIZ_SIZE(evt->length)); 444562306a36Sopenharmony_ci 444662306a36Sopenharmony_ci if (dwc->imod_interval) { 444762306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), DWC3_GEVNTCOUNT_EHB); 444862306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_DEV_IMOD(0), dwc->imod_interval); 444962306a36Sopenharmony_ci } 445062306a36Sopenharmony_ci 445162306a36Sopenharmony_ci /* Keep the clearing of DWC3_EVENT_PENDING at the end */ 445262306a36Sopenharmony_ci evt->flags &= ~DWC3_EVENT_PENDING; 445362306a36Sopenharmony_ci 445462306a36Sopenharmony_ci return ret; 445562306a36Sopenharmony_ci} 445662306a36Sopenharmony_ci 445762306a36Sopenharmony_cistatic irqreturn_t dwc3_thread_interrupt(int irq, void *_evt) 445862306a36Sopenharmony_ci{ 445962306a36Sopenharmony_ci struct dwc3_event_buffer *evt = _evt; 446062306a36Sopenharmony_ci struct dwc3 *dwc = evt->dwc; 446162306a36Sopenharmony_ci unsigned long flags; 446262306a36Sopenharmony_ci irqreturn_t ret = IRQ_NONE; 446362306a36Sopenharmony_ci 446462306a36Sopenharmony_ci local_bh_disable(); 446562306a36Sopenharmony_ci spin_lock_irqsave(&dwc->lock, flags); 446662306a36Sopenharmony_ci ret = dwc3_process_event_buf(evt); 446762306a36Sopenharmony_ci spin_unlock_irqrestore(&dwc->lock, flags); 446862306a36Sopenharmony_ci local_bh_enable(); 446962306a36Sopenharmony_ci 447062306a36Sopenharmony_ci return ret; 447162306a36Sopenharmony_ci} 447262306a36Sopenharmony_ci 447362306a36Sopenharmony_cistatic irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt) 447462306a36Sopenharmony_ci{ 447562306a36Sopenharmony_ci struct dwc3 *dwc = evt->dwc; 447662306a36Sopenharmony_ci u32 amount; 447762306a36Sopenharmony_ci u32 count; 447862306a36Sopenharmony_ci 447962306a36Sopenharmony_ci if (pm_runtime_suspended(dwc->dev)) { 448062306a36Sopenharmony_ci dwc->pending_events = true; 448162306a36Sopenharmony_ci /* 448262306a36Sopenharmony_ci * Trigger runtime resume. The get() function will be balanced 448362306a36Sopenharmony_ci * after processing the pending events in dwc3_process_pending 448462306a36Sopenharmony_ci * events(). 448562306a36Sopenharmony_ci */ 448662306a36Sopenharmony_ci pm_runtime_get(dwc->dev); 448762306a36Sopenharmony_ci disable_irq_nosync(dwc->irq_gadget); 448862306a36Sopenharmony_ci return IRQ_HANDLED; 448962306a36Sopenharmony_ci } 449062306a36Sopenharmony_ci 449162306a36Sopenharmony_ci /* 449262306a36Sopenharmony_ci * With PCIe legacy interrupt, test shows that top-half irq handler can 449362306a36Sopenharmony_ci * be called again after HW interrupt deassertion. Check if bottom-half 449462306a36Sopenharmony_ci * irq event handler completes before caching new event to prevent 449562306a36Sopenharmony_ci * losing events. 449662306a36Sopenharmony_ci */ 449762306a36Sopenharmony_ci if (evt->flags & DWC3_EVENT_PENDING) 449862306a36Sopenharmony_ci return IRQ_HANDLED; 449962306a36Sopenharmony_ci 450062306a36Sopenharmony_ci count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0)); 450162306a36Sopenharmony_ci count &= DWC3_GEVNTCOUNT_MASK; 450262306a36Sopenharmony_ci if (!count) 450362306a36Sopenharmony_ci return IRQ_NONE; 450462306a36Sopenharmony_ci 450562306a36Sopenharmony_ci evt->count = count; 450662306a36Sopenharmony_ci evt->flags |= DWC3_EVENT_PENDING; 450762306a36Sopenharmony_ci 450862306a36Sopenharmony_ci /* Mask interrupt */ 450962306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), 451062306a36Sopenharmony_ci DWC3_GEVNTSIZ_INTMASK | DWC3_GEVNTSIZ_SIZE(evt->length)); 451162306a36Sopenharmony_ci 451262306a36Sopenharmony_ci amount = min(count, evt->length - evt->lpos); 451362306a36Sopenharmony_ci memcpy(evt->cache + evt->lpos, evt->buf + evt->lpos, amount); 451462306a36Sopenharmony_ci 451562306a36Sopenharmony_ci if (amount < count) 451662306a36Sopenharmony_ci memcpy(evt->cache, evt->buf, count - amount); 451762306a36Sopenharmony_ci 451862306a36Sopenharmony_ci dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), count); 451962306a36Sopenharmony_ci 452062306a36Sopenharmony_ci return IRQ_WAKE_THREAD; 452162306a36Sopenharmony_ci} 452262306a36Sopenharmony_ci 452362306a36Sopenharmony_cistatic irqreturn_t dwc3_interrupt(int irq, void *_evt) 452462306a36Sopenharmony_ci{ 452562306a36Sopenharmony_ci struct dwc3_event_buffer *evt = _evt; 452662306a36Sopenharmony_ci 452762306a36Sopenharmony_ci return dwc3_check_event_buf(evt); 452862306a36Sopenharmony_ci} 452962306a36Sopenharmony_ci 453062306a36Sopenharmony_cistatic int dwc3_gadget_get_irq(struct dwc3 *dwc) 453162306a36Sopenharmony_ci{ 453262306a36Sopenharmony_ci struct platform_device *dwc3_pdev = to_platform_device(dwc->dev); 453362306a36Sopenharmony_ci int irq; 453462306a36Sopenharmony_ci 453562306a36Sopenharmony_ci irq = platform_get_irq_byname_optional(dwc3_pdev, "peripheral"); 453662306a36Sopenharmony_ci if (irq > 0) 453762306a36Sopenharmony_ci goto out; 453862306a36Sopenharmony_ci 453962306a36Sopenharmony_ci if (irq == -EPROBE_DEFER) 454062306a36Sopenharmony_ci goto out; 454162306a36Sopenharmony_ci 454262306a36Sopenharmony_ci irq = platform_get_irq_byname_optional(dwc3_pdev, "dwc_usb3"); 454362306a36Sopenharmony_ci if (irq > 0) 454462306a36Sopenharmony_ci goto out; 454562306a36Sopenharmony_ci 454662306a36Sopenharmony_ci if (irq == -EPROBE_DEFER) 454762306a36Sopenharmony_ci goto out; 454862306a36Sopenharmony_ci 454962306a36Sopenharmony_ci irq = platform_get_irq(dwc3_pdev, 0); 455062306a36Sopenharmony_ci 455162306a36Sopenharmony_ciout: 455262306a36Sopenharmony_ci return irq; 455362306a36Sopenharmony_ci} 455462306a36Sopenharmony_ci 455562306a36Sopenharmony_cistatic void dwc_gadget_release(struct device *dev) 455662306a36Sopenharmony_ci{ 455762306a36Sopenharmony_ci struct usb_gadget *gadget = container_of(dev, struct usb_gadget, dev); 455862306a36Sopenharmony_ci 455962306a36Sopenharmony_ci kfree(gadget); 456062306a36Sopenharmony_ci} 456162306a36Sopenharmony_ci 456262306a36Sopenharmony_ci/** 456362306a36Sopenharmony_ci * dwc3_gadget_init - initializes gadget related registers 456462306a36Sopenharmony_ci * @dwc: pointer to our controller context structure 456562306a36Sopenharmony_ci * 456662306a36Sopenharmony_ci * Returns 0 on success otherwise negative errno. 456762306a36Sopenharmony_ci */ 456862306a36Sopenharmony_ciint dwc3_gadget_init(struct dwc3 *dwc) 456962306a36Sopenharmony_ci{ 457062306a36Sopenharmony_ci int ret; 457162306a36Sopenharmony_ci int irq; 457262306a36Sopenharmony_ci struct device *dev; 457362306a36Sopenharmony_ci 457462306a36Sopenharmony_ci irq = dwc3_gadget_get_irq(dwc); 457562306a36Sopenharmony_ci if (irq < 0) { 457662306a36Sopenharmony_ci ret = irq; 457762306a36Sopenharmony_ci goto err0; 457862306a36Sopenharmony_ci } 457962306a36Sopenharmony_ci 458062306a36Sopenharmony_ci dwc->irq_gadget = irq; 458162306a36Sopenharmony_ci 458262306a36Sopenharmony_ci dwc->ep0_trb = dma_alloc_coherent(dwc->sysdev, 458362306a36Sopenharmony_ci sizeof(*dwc->ep0_trb) * 2, 458462306a36Sopenharmony_ci &dwc->ep0_trb_addr, GFP_KERNEL); 458562306a36Sopenharmony_ci if (!dwc->ep0_trb) { 458662306a36Sopenharmony_ci dev_err(dwc->dev, "failed to allocate ep0 trb\n"); 458762306a36Sopenharmony_ci ret = -ENOMEM; 458862306a36Sopenharmony_ci goto err0; 458962306a36Sopenharmony_ci } 459062306a36Sopenharmony_ci 459162306a36Sopenharmony_ci dwc->setup_buf = kzalloc(DWC3_EP0_SETUP_SIZE, GFP_KERNEL); 459262306a36Sopenharmony_ci if (!dwc->setup_buf) { 459362306a36Sopenharmony_ci ret = -ENOMEM; 459462306a36Sopenharmony_ci goto err1; 459562306a36Sopenharmony_ci } 459662306a36Sopenharmony_ci 459762306a36Sopenharmony_ci dwc->bounce = dma_alloc_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, 459862306a36Sopenharmony_ci &dwc->bounce_addr, GFP_KERNEL); 459962306a36Sopenharmony_ci if (!dwc->bounce) { 460062306a36Sopenharmony_ci ret = -ENOMEM; 460162306a36Sopenharmony_ci goto err2; 460262306a36Sopenharmony_ci } 460362306a36Sopenharmony_ci 460462306a36Sopenharmony_ci init_completion(&dwc->ep0_in_setup); 460562306a36Sopenharmony_ci dwc->gadget = kzalloc(sizeof(struct usb_gadget), GFP_KERNEL); 460662306a36Sopenharmony_ci if (!dwc->gadget) { 460762306a36Sopenharmony_ci ret = -ENOMEM; 460862306a36Sopenharmony_ci goto err3; 460962306a36Sopenharmony_ci } 461062306a36Sopenharmony_ci 461162306a36Sopenharmony_ci 461262306a36Sopenharmony_ci usb_initialize_gadget(dwc->dev, dwc->gadget, dwc_gadget_release); 461362306a36Sopenharmony_ci dev = &dwc->gadget->dev; 461462306a36Sopenharmony_ci dev->platform_data = dwc; 461562306a36Sopenharmony_ci dwc->gadget->ops = &dwc3_gadget_ops; 461662306a36Sopenharmony_ci dwc->gadget->speed = USB_SPEED_UNKNOWN; 461762306a36Sopenharmony_ci dwc->gadget->ssp_rate = USB_SSP_GEN_UNKNOWN; 461862306a36Sopenharmony_ci dwc->gadget->sg_supported = true; 461962306a36Sopenharmony_ci dwc->gadget->name = "dwc3-gadget"; 462062306a36Sopenharmony_ci dwc->gadget->lpm_capable = !dwc->usb2_gadget_lpm_disable; 462162306a36Sopenharmony_ci dwc->gadget->wakeup_capable = true; 462262306a36Sopenharmony_ci 462362306a36Sopenharmony_ci /* 462462306a36Sopenharmony_ci * FIXME We might be setting max_speed to <SUPER, however versions 462562306a36Sopenharmony_ci * <2.20a of dwc3 have an issue with metastability (documented 462662306a36Sopenharmony_ci * elsewhere in this driver) which tells us we can't set max speed to 462762306a36Sopenharmony_ci * anything lower than SUPER. 462862306a36Sopenharmony_ci * 462962306a36Sopenharmony_ci * Because gadget.max_speed is only used by composite.c and function 463062306a36Sopenharmony_ci * drivers (i.e. it won't go into dwc3's registers) we are allowing this 463162306a36Sopenharmony_ci * to happen so we avoid sending SuperSpeed Capability descriptor 463262306a36Sopenharmony_ci * together with our BOS descriptor as that could confuse host into 463362306a36Sopenharmony_ci * thinking we can handle super speed. 463462306a36Sopenharmony_ci * 463562306a36Sopenharmony_ci * Note that, in fact, we won't even support GetBOS requests when speed 463662306a36Sopenharmony_ci * is less than super speed because we don't have means, yet, to tell 463762306a36Sopenharmony_ci * composite.c that we are USB 2.0 + LPM ECN. 463862306a36Sopenharmony_ci */ 463962306a36Sopenharmony_ci if (DWC3_VER_IS_PRIOR(DWC3, 220A) && 464062306a36Sopenharmony_ci !dwc->dis_metastability_quirk) 464162306a36Sopenharmony_ci dev_info(dwc->dev, "changing max_speed on rev %08x\n", 464262306a36Sopenharmony_ci dwc->revision); 464362306a36Sopenharmony_ci 464462306a36Sopenharmony_ci dwc->gadget->max_speed = dwc->maximum_speed; 464562306a36Sopenharmony_ci dwc->gadget->max_ssp_rate = dwc->max_ssp_rate; 464662306a36Sopenharmony_ci 464762306a36Sopenharmony_ci /* 464862306a36Sopenharmony_ci * REVISIT: Here we should clear all pending IRQs to be 464962306a36Sopenharmony_ci * sure we're starting from a well known location. 465062306a36Sopenharmony_ci */ 465162306a36Sopenharmony_ci 465262306a36Sopenharmony_ci ret = dwc3_gadget_init_endpoints(dwc, dwc->num_eps); 465362306a36Sopenharmony_ci if (ret) 465462306a36Sopenharmony_ci goto err4; 465562306a36Sopenharmony_ci 465662306a36Sopenharmony_ci ret = usb_add_gadget(dwc->gadget); 465762306a36Sopenharmony_ci if (ret) { 465862306a36Sopenharmony_ci dev_err(dwc->dev, "failed to add gadget\n"); 465962306a36Sopenharmony_ci goto err5; 466062306a36Sopenharmony_ci } 466162306a36Sopenharmony_ci 466262306a36Sopenharmony_ci if (DWC3_IP_IS(DWC32) && dwc->maximum_speed == USB_SPEED_SUPER_PLUS) 466362306a36Sopenharmony_ci dwc3_gadget_set_ssp_rate(dwc->gadget, dwc->max_ssp_rate); 466462306a36Sopenharmony_ci else 466562306a36Sopenharmony_ci dwc3_gadget_set_speed(dwc->gadget, dwc->maximum_speed); 466662306a36Sopenharmony_ci 466762306a36Sopenharmony_ci return 0; 466862306a36Sopenharmony_ci 466962306a36Sopenharmony_cierr5: 467062306a36Sopenharmony_ci dwc3_gadget_free_endpoints(dwc); 467162306a36Sopenharmony_cierr4: 467262306a36Sopenharmony_ci usb_put_gadget(dwc->gadget); 467362306a36Sopenharmony_ci dwc->gadget = NULL; 467462306a36Sopenharmony_cierr3: 467562306a36Sopenharmony_ci dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce, 467662306a36Sopenharmony_ci dwc->bounce_addr); 467762306a36Sopenharmony_ci 467862306a36Sopenharmony_cierr2: 467962306a36Sopenharmony_ci kfree(dwc->setup_buf); 468062306a36Sopenharmony_ci 468162306a36Sopenharmony_cierr1: 468262306a36Sopenharmony_ci dma_free_coherent(dwc->sysdev, sizeof(*dwc->ep0_trb) * 2, 468362306a36Sopenharmony_ci dwc->ep0_trb, dwc->ep0_trb_addr); 468462306a36Sopenharmony_ci 468562306a36Sopenharmony_cierr0: 468662306a36Sopenharmony_ci return ret; 468762306a36Sopenharmony_ci} 468862306a36Sopenharmony_ci 468962306a36Sopenharmony_ci/* -------------------------------------------------------------------------- */ 469062306a36Sopenharmony_ci 469162306a36Sopenharmony_civoid dwc3_gadget_exit(struct dwc3 *dwc) 469262306a36Sopenharmony_ci{ 469362306a36Sopenharmony_ci if (!dwc->gadget) 469462306a36Sopenharmony_ci return; 469562306a36Sopenharmony_ci 469662306a36Sopenharmony_ci usb_del_gadget(dwc->gadget); 469762306a36Sopenharmony_ci dwc3_gadget_free_endpoints(dwc); 469862306a36Sopenharmony_ci usb_put_gadget(dwc->gadget); 469962306a36Sopenharmony_ci dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce, 470062306a36Sopenharmony_ci dwc->bounce_addr); 470162306a36Sopenharmony_ci kfree(dwc->setup_buf); 470262306a36Sopenharmony_ci dma_free_coherent(dwc->sysdev, sizeof(*dwc->ep0_trb) * 2, 470362306a36Sopenharmony_ci dwc->ep0_trb, dwc->ep0_trb_addr); 470462306a36Sopenharmony_ci} 470562306a36Sopenharmony_ci 470662306a36Sopenharmony_ciint dwc3_gadget_suspend(struct dwc3 *dwc) 470762306a36Sopenharmony_ci{ 470862306a36Sopenharmony_ci unsigned long flags; 470962306a36Sopenharmony_ci int ret; 471062306a36Sopenharmony_ci 471162306a36Sopenharmony_ci ret = dwc3_gadget_soft_disconnect(dwc); 471262306a36Sopenharmony_ci if (ret) 471362306a36Sopenharmony_ci goto err; 471462306a36Sopenharmony_ci 471562306a36Sopenharmony_ci spin_lock_irqsave(&dwc->lock, flags); 471662306a36Sopenharmony_ci if (dwc->gadget_driver) 471762306a36Sopenharmony_ci dwc3_disconnect_gadget(dwc); 471862306a36Sopenharmony_ci spin_unlock_irqrestore(&dwc->lock, flags); 471962306a36Sopenharmony_ci 472062306a36Sopenharmony_ci return 0; 472162306a36Sopenharmony_ci 472262306a36Sopenharmony_cierr: 472362306a36Sopenharmony_ci /* 472462306a36Sopenharmony_ci * Attempt to reset the controller's state. Likely no 472562306a36Sopenharmony_ci * communication can be established until the host 472662306a36Sopenharmony_ci * performs a port reset. 472762306a36Sopenharmony_ci */ 472862306a36Sopenharmony_ci if (dwc->softconnect) 472962306a36Sopenharmony_ci dwc3_gadget_soft_connect(dwc); 473062306a36Sopenharmony_ci 473162306a36Sopenharmony_ci return ret; 473262306a36Sopenharmony_ci} 473362306a36Sopenharmony_ci 473462306a36Sopenharmony_ciint dwc3_gadget_resume(struct dwc3 *dwc) 473562306a36Sopenharmony_ci{ 473662306a36Sopenharmony_ci if (!dwc->gadget_driver || !dwc->softconnect) 473762306a36Sopenharmony_ci return 0; 473862306a36Sopenharmony_ci 473962306a36Sopenharmony_ci return dwc3_gadget_soft_connect(dwc); 474062306a36Sopenharmony_ci} 474162306a36Sopenharmony_ci 474262306a36Sopenharmony_civoid dwc3_gadget_process_pending_events(struct dwc3 *dwc) 474362306a36Sopenharmony_ci{ 474462306a36Sopenharmony_ci if (dwc->pending_events) { 474562306a36Sopenharmony_ci dwc3_interrupt(dwc->irq_gadget, dwc->ev_buf); 474662306a36Sopenharmony_ci dwc3_thread_interrupt(dwc->irq_gadget, dwc->ev_buf); 474762306a36Sopenharmony_ci pm_runtime_put(dwc->dev); 474862306a36Sopenharmony_ci dwc->pending_events = false; 474962306a36Sopenharmony_ci enable_irq(dwc->irq_gadget); 475062306a36Sopenharmony_ci } 475162306a36Sopenharmony_ci} 4752