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(&params, 0, sizeof(params));
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci	return dwc3_send_gadget_ep_cmd(dep, cmd, &params);
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(&params, 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			&params);
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(&params, 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, &params);
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(&params, 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, &params);
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(&params, 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, &params);
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(&params, 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, &params);
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(&params, 0, sizeof(params));
173162306a36Sopenharmony_ci	ret = dwc3_send_gadget_ep_cmd(dep, cmd, &params);
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, &params);
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(&params, 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				&params);
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