Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 23063b37 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

Merge tag 'dwc3-for-v3.5' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next

usb: dwc3: patches for v3.5 merge window

This pull request contains one workaround for a Silicon
Issue found on all RTL releases prior to 2.20a, which
would cause a metastability state on Run/Stop bit.

We also have some patches implementing a few extra Standard
requests introduced by USB3 spec (Set SEL and Set Isoch Delay),
as well as one patch, which has been pending for a long time,
implementing LPM support.

Last, but not least, we are splitting the host address space
out of the dwc3 core driver otherwise xHCI won't be able to
request_mem_region() its own address space. This patch is
only needed because we are (as we should) re-using the xHCI
driver, which is a completely separate module.

Together with these three big changes, come a few extra preparatory
patches which most move code around, define macros and so on, as
well as a fix for Isochronous transfers which hasn't been triggered
before.

[ resolved conflicts and build error in drivers/usb/dwc3/gadget.c - gregkh]
parents a5c708e8 3ef35faf
Loading
Loading
Loading
Loading
+18 −13
Original line number Diff line number Diff line
@@ -410,7 +410,6 @@ static int __devinit dwc3_probe(struct platform_device *pdev)
	struct device		*dev = &pdev->dev;

	int			ret = -ENOMEM;
	int			irq;

	void __iomem		*regs;
	void			*mem;
@@ -425,15 +424,28 @@ static int __devinit dwc3_probe(struct platform_device *pdev)
	dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1);
	dwc->mem = mem;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (!res) {
		dev_err(dev, "missing resource\n");
		dev_err(dev, "missing IRQ\n");
		return -ENODEV;
	}
	dwc->xhci_resources[1] = *res;

	dwc->res = res;
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(dev, "missing memory resource\n");
		return -ENODEV;
	}
	dwc->xhci_resources[0] = *res;
	dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
					DWC3_XHCI_REGS_END;

	res = devm_request_mem_region(dev, res->start, resource_size(res),
	 /*
	  * Request memory region but exclude xHCI regs,
	  * since it will be requested by the xhci-plat driver.
	  */
	res = devm_request_mem_region(dev, res->start + DWC3_GLOBALS_REGS_START,
			resource_size(res) - DWC3_GLOBALS_REGS_START,
			dev_name(dev));
	if (!res) {
		dev_err(dev, "can't request mem region\n");
@@ -446,19 +458,12 @@ static int __devinit dwc3_probe(struct platform_device *pdev)
		return -ENOMEM;
	}

	irq = platform_get_irq(pdev, 0);
	if (irq < 0) {
		dev_err(dev, "missing IRQ\n");
		return -ENODEV;
	}

	spin_lock_init(&dwc->lock);
	platform_set_drvdata(pdev, dwc);

	dwc->regs	= regs;
	dwc->regs_size	= resource_size(res);
	dwc->dev	= dev;
	dwc->irq	= irq;

	if (!strncmp("super", maximum_speed, 5))
		dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
+34 −5
Original line number Diff line number Diff line
@@ -51,7 +51,9 @@
#include <linux/usb/gadget.h>

/* Global constants */
#define DWC3_EP0_BOUNCE_SIZE	512
#define DWC3_ENDPOINTS_NUM	32
#define DWC3_XHCI_RESOURCES_NUM	2

#define DWC3_EVENT_BUFFERS_SIZE	PAGE_SIZE
#define DWC3_EVENT_TYPE_MASK	0xfe
@@ -75,6 +77,16 @@
#define DWC3_GSNPSID_MASK	0xffff0000
#define DWC3_GSNPSREV_MASK	0xffff

/* DWC3 registers memory space boundries */
#define DWC3_XHCI_REGS_START		0x0
#define DWC3_XHCI_REGS_END		0x7fff
#define DWC3_GLOBALS_REGS_START		0xc100
#define DWC3_GLOBALS_REGS_END		0xc6ff
#define DWC3_DEVICE_REGS_START		0xc700
#define DWC3_DEVICE_REGS_END		0xcbff
#define DWC3_OTG_REGS_START		0xcc00
#define DWC3_OTG_REGS_END		0xccff

/* Global Registers */
#define DWC3_GSBUSCFG0		0xc100
#define DWC3_GSBUSCFG1		0xc104
@@ -183,6 +195,7 @@
#define DWC3_GHWPARAMS1_EN_PWROPT_CLK	1

/* Device Configuration Register */
#define DWC3_DCFG_LPM_CAP	(1 << 22)
#define DWC3_DCFG_DEVADDR(addr)	((addr) << 3)
#define DWC3_DCFG_DEVADDR_MASK	DWC3_DCFG_DEVADDR(0x7f)

@@ -272,12 +285,14 @@
#define DWC3_DGCMD_SET_ENDPOINT_NRDY	0x0c
#define DWC3_DGCMD_RUN_SOC_BUS_LOOPBACK	0x10

#define DWC3_DGCMD_STATUS(n)		(((n) >> 15) & 1)
#define DWC3_DGCMD_CMDACT		(1 << 10)

/* Device Endpoint Command Register */
#define DWC3_DEPCMD_PARAM_SHIFT		16
#define DWC3_DEPCMD_PARAM(x)		((x) << DWC3_DEPCMD_PARAM_SHIFT)
#define DWC3_DEPCMD_GET_RSC_IDX(x)     (((x) >> DWC3_DEPCMD_PARAM_SHIFT) & 0x7f)
#define DWC3_DEPCMD_STATUS_MASK		(0x0f << 12)
#define DWC3_DEPCMD_STATUS(x)		(((x) & DWC3_DEPCMD_STATUS_MASK) >> 12)
#define DWC3_DEPCMD_STATUS(x)		(((x) >> 15) & 1)
#define DWC3_DEPCMD_HIPRI_FORCERM	(1 << 11)
#define DWC3_DEPCMD_CMDACT		(1 << 10)
#define DWC3_DEPCMD_CMDIOC		(1 << 8)
@@ -560,6 +575,11 @@ struct dwc3_request {
 * @setup_packet_pending: true when there's a Setup Packet in FIFO. Workaround
 * @needs_fifo_resize: not all users might want fifo resizing, flag it
 * @resize_fifos: tells us it's ok to reconfigure our TxFIFO sizes.
 * @isoch_delay: wValue from Set Isochronous Delay request;
 * @u2sel: parameter from Set SEL request.
 * @u2pel: parameter from Set SEL request.
 * @u1sel: parameter from Set SEL request.
 * @u1pel: parameter from Set SEL request.
 * @ep0_next_event: hold the next expected event
 * @ep0state: state of endpoint zero
 * @link_state: link state
@@ -582,7 +602,7 @@ struct dwc3 {
	struct device		*dev;

	struct platform_device	*xhci;
	struct resource		*res;
	struct resource		xhci_resources[DWC3_XHCI_RESOURCES_NUM];

	struct dwc3_event_buffer **ev_buffs;
	struct dwc3_ep		*eps[DWC3_ENDPOINTS_NUM];
@@ -593,8 +613,6 @@ struct dwc3 {
	void __iomem		*regs;
	size_t			regs_size;

	int			irq;

	u32			num_event_buffers;
	u32			u1u2;
	u32			maximum_speed;
@@ -608,6 +626,10 @@ struct dwc3 {
#define DWC3_REVISION_185A	0x5533185a
#define DWC3_REVISION_188A	0x5533188a
#define DWC3_REVISION_190A	0x5533190a
#define DWC3_REVISION_200A	0x5533200a
#define DWC3_REVISION_202A	0x5533202a
#define DWC3_REVISION_210A	0x5533210a
#define DWC3_REVISION_220A	0x5533220a

	unsigned		is_selfpowered:1;
	unsigned		three_stage_setup:1;
@@ -624,7 +646,14 @@ struct dwc3 {
	enum dwc3_link_state	link_state;
	enum dwc3_device_state	dev_state;

	u16			isoch_delay;
	u16			u2sel;
	u16			u2pel;
	u8			u1sel;
	u8			u1pel;

	u8			speed;

	void			*mem;

	struct dwc3_hwparams	hwparams;
+21 −11
Original line number Diff line number Diff line
@@ -49,7 +49,6 @@
#include <linux/of.h>

#include "core.h"
#include "io.h"

/*
 * All these registers belong to OMAP's Wrapper around the
@@ -143,6 +142,17 @@ struct dwc3_omap {
	u32			dma_status:1;
};

static inline u32 dwc3_omap_readl(void __iomem *base, u32 offset)
{
	return readl(base + offset);
}

static inline void dwc3_omap_writel(void __iomem *base, u32 offset, u32 value)
{
	writel(value, base + offset);
}


static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
{
	struct dwc3_omap	*omap = _omap;
@@ -150,7 +160,7 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)

	spin_lock(&omap->lock);

	reg = dwc3_readl(omap->base, USBOTGSS_IRQSTATUS_1);
	reg = dwc3_omap_readl(omap->base, USBOTGSS_IRQSTATUS_1);

	if (reg & USBOTGSS_IRQ1_DMADISABLECLR) {
		dev_dbg(omap->dev, "DMA Disable was Cleared\n");
@@ -184,10 +194,10 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
	if (reg & USBOTGSS_IRQ1_IDPULLUP_FALL)
		dev_dbg(omap->dev, "IDPULLUP Fall\n");

	dwc3_writel(omap->base, USBOTGSS_IRQSTATUS_1, reg);
	dwc3_omap_writel(omap->base, USBOTGSS_IRQSTATUS_1, reg);

	reg = dwc3_readl(omap->base, USBOTGSS_IRQSTATUS_0);
	dwc3_writel(omap->base, USBOTGSS_IRQSTATUS_0, reg);
	reg = dwc3_omap_readl(omap->base, USBOTGSS_IRQSTATUS_0);
	dwc3_omap_writel(omap->base, USBOTGSS_IRQSTATUS_0, reg);

	spin_unlock(&omap->lock);

@@ -270,7 +280,7 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
	omap->base	= base;
	omap->dwc3	= dwc3;

	reg = dwc3_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS);
	reg = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS);

	utmi_mode = of_get_property(node, "utmi-mode", &size);
	if (utmi_mode && size == sizeof(*utmi_mode)) {
@@ -293,10 +303,10 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
		}
	}

	dwc3_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, reg);
	dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, reg);

	/* check the DMA Status */
	reg = dwc3_readl(omap->base, USBOTGSS_SYSCONFIG);
	reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG);
	omap->dma_status = !!(reg & USBOTGSS_SYSCONFIG_DMADISABLE);

	/* Set No-Idle and No-Standby */
@@ -306,7 +316,7 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
	reg |= (USBOTGSS_SYSCONFIG_STANDBYMODE(USBOTGSS_STANDBYMODE_NO_STANDBY)
		| USBOTGSS_SYSCONFIG_IDLEMODE(USBOTGSS_IDLEMODE_NO_IDLE));

	dwc3_writel(omap->base, USBOTGSS_SYSCONFIG, reg);
	dwc3_omap_writel(omap->base, USBOTGSS_SYSCONFIG, reg);

	ret = devm_request_irq(dev, omap->irq, dwc3_omap_interrupt, 0,
			"dwc3-omap", omap);
@@ -318,7 +328,7 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)

	/* enable all IRQs */
	reg = USBOTGSS_IRQO_COREIRQ_ST;
	dwc3_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, reg);
	dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, reg);

	reg = (USBOTGSS_IRQ1_OEVT |
			USBOTGSS_IRQ1_DRVVBUS_RISE |
@@ -330,7 +340,7 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
			USBOTGSS_IRQ1_DISCHRGVBUS_FALL |
			USBOTGSS_IRQ1_IDPULLUP_FALL);

	dwc3_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, reg);
	dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, reg);

	ret = platform_device_add_resources(dwc3, pdev->resource,
			pdev->num_resources);
+144 −11
Original line number Diff line number Diff line
@@ -261,6 +261,7 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc,
{
	struct dwc3_ep		*dep;
	u32			recip;
	u32			reg;
	u16			usb_status = 0;
	__le16			*response_pkt;

@@ -268,10 +269,18 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc,
	switch (recip) {
	case USB_RECIP_DEVICE:
		/*
		 * We are self-powered. U1/U2/LTM will be set later
		 * once we handle this states. RemoteWakeup is 0 on SS
		 * LTM will be set once we know how to set this in HW.
		 */
		usb_status |= dwc->is_selfpowered << USB_DEVICE_SELF_POWERED;

		if (dwc->speed == DWC3_DSTS_SUPERSPEED) {
			reg = dwc3_readl(dwc->regs, DWC3_DCTL);
			if (reg & DWC3_DCTL_INITU1ENA)
				usb_status |= 1 << USB_DEV_STAT_U1_ENABLED;
			if (reg & DWC3_DCTL_INITU2ENA)
				usb_status |= 1 << USB_DEV_STAT_U2_ENABLED;
		}

		break;

	case USB_RECIP_INTERFACE:
@@ -312,6 +321,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
	u32			recip;
	u32			wValue;
	u32			wIndex;
	u32			reg;
	int			ret;

	wValue = le16_to_cpu(ctrl->wValue);
@@ -320,29 +330,43 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
	switch (recip) {
	case USB_RECIP_DEVICE:

		switch (wValue) {
		case USB_DEVICE_REMOTE_WAKEUP:
			break;
		/*
		 * 9.4.1 says only only for SS, in AddressState only for
		 * default control pipe
		 */
		switch (wValue) {
		case USB_DEVICE_U1_ENABLE:
		case USB_DEVICE_U2_ENABLE:
		case USB_DEVICE_LTM_ENABLE:
			if (dwc->dev_state != DWC3_CONFIGURED_STATE)
				return -EINVAL;
			if (dwc->speed != DWC3_DSTS_SUPERSPEED)
				return -EINVAL;
		}

		/* XXX add U[12] & LTM */
		switch (wValue) {
		case USB_DEVICE_REMOTE_WAKEUP:
			break;
		case USB_DEVICE_U1_ENABLE:
			reg = dwc3_readl(dwc->regs, DWC3_DCTL);
			if (set)
				reg |= DWC3_DCTL_INITU1ENA;
			else
				reg &= ~DWC3_DCTL_INITU1ENA;
			dwc3_writel(dwc->regs, DWC3_DCTL, reg);
			break;

		case USB_DEVICE_U2_ENABLE:
			if (dwc->dev_state != DWC3_CONFIGURED_STATE)
				return -EINVAL;
			if (dwc->speed != DWC3_DSTS_SUPERSPEED)
				return -EINVAL;

			reg = dwc3_readl(dwc->regs, DWC3_DCTL);
			if (set)
				reg |= DWC3_DCTL_INITU2ENA;
			else
				reg &= ~DWC3_DCTL_INITU2ENA;
			dwc3_writel(dwc->regs, DWC3_DCTL, reg);
			break;

		case USB_DEVICE_LTM_ENABLE:
			return -EINVAL;
			break;

		case USB_DEVICE_TEST_MODE:
@@ -469,6 +493,107 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
	return ret;
}

static void dwc3_ep0_set_sel_cmpl(struct usb_ep *ep, struct usb_request *req)
{
	struct dwc3_ep	*dep = to_dwc3_ep(ep);
	struct dwc3	*dwc = dep->dwc;

	u32		param = 0;
	u32		reg;

	struct timing {
		u8	u1sel;
		u8	u1pel;
		u16	u2sel;
		u16	u2pel;
	} __packed timing;

	int		ret;

	memcpy(&timing, req->buf, sizeof(timing));

	dwc->u1sel = timing.u1sel;
	dwc->u1pel = timing.u1pel;
	dwc->u2sel = timing.u2sel;
	dwc->u2pel = timing.u2pel;

	reg = dwc3_readl(dwc->regs, DWC3_DCTL);
	if (reg & DWC3_DCTL_INITU2ENA)
		param = dwc->u2pel;
	if (reg & DWC3_DCTL_INITU1ENA)
		param = dwc->u1pel;

	/*
	 * According to Synopsys Databook, if parameter is
	 * greater than 125, a value of zero should be
	 * programmed in the register.
	 */
	if (param > 125)
		param = 0;

	/* now that we have the time, issue DGCMD Set Sel */
	ret = dwc3_send_gadget_generic_command(dwc,
			DWC3_DGCMD_SET_PERIODIC_PAR, param);
	WARN_ON(ret < 0);
}

static int dwc3_ep0_set_sel(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
{
	struct dwc3_ep	*dep;
	u16		wLength;
	u16		wValue;

	if (dwc->dev_state == DWC3_DEFAULT_STATE)
		return -EINVAL;

	wValue = le16_to_cpu(ctrl->wValue);
	wLength = le16_to_cpu(ctrl->wLength);

	if (wLength != 6) {
		dev_err(dwc->dev, "Set SEL should be 6 bytes, got %d\n",
				wLength);
		return -EINVAL;
	}

	/*
	 * To handle Set SEL we need to receive 6 bytes from Host. So let's
	 * queue a usb_request for 6 bytes.
	 *
	 * Remember, though, this controller can't handle non-wMaxPacketSize
	 * aligned transfers on the OUT direction, so we queue a request for
	 * wMaxPacketSize instead.
	 */
	dep = dwc->eps[0];
	dwc->ep0_usb_req.dep = dep;
	dwc->ep0_usb_req.request.length = dep->endpoint.maxpacket;
	dwc->ep0_usb_req.request.buf = dwc->setup_buf;
	dwc->ep0_usb_req.request.complete = dwc3_ep0_set_sel_cmpl;

	return __dwc3_gadget_ep0_queue(dep, &dwc->ep0_usb_req);
}

static int dwc3_ep0_set_isoch_delay(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
{
	u16		wLength;
	u16		wValue;
	u16		wIndex;

	wValue = le16_to_cpu(ctrl->wValue);
	wLength = le16_to_cpu(ctrl->wLength);
	wIndex = le16_to_cpu(ctrl->wIndex);

	if (wIndex || wLength)
		return -EINVAL;

	/*
	 * REVISIT It's unclear from Databook what to do with this
	 * value. For now, just cache it.
	 */
	dwc->isoch_delay = wValue;

	return 0;
}

static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
{
	int ret;
@@ -494,6 +619,14 @@ static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
		dev_vdbg(dwc->dev, "USB_REQ_SET_CONFIGURATION\n");
		ret = dwc3_ep0_set_config(dwc, ctrl);
		break;
	case USB_REQ_SET_SEL:
		dev_vdbg(dwc->dev, "USB_REQ_SET_SEL\n");
		ret = dwc3_ep0_set_sel(dwc, ctrl);
		break;
	case USB_REQ_SET_ISOCH_DELAY:
		dev_vdbg(dwc->dev, "USB_REQ_SET_ISOCH_DELAY\n");
		ret = dwc3_ep0_set_isoch_delay(dwc, ctrl);
		break;
	default:
		dev_vdbg(dwc->dev, "Forwarding to gadget driver\n");
		ret = dwc3_ep0_delegate_req(dwc, ctrl);
+89 −25
Original line number Diff line number Diff line
@@ -276,6 +276,33 @@ static const char *dwc3_gadget_ep_cmd_string(u8 cmd)
	}
}

int dwc3_send_gadget_generic_command(struct dwc3 *dwc, int cmd, u32 param)
{
	u32		timeout = 500;
	u32		reg;

	dwc3_writel(dwc->regs, DWC3_DGCMDPAR, param);
	dwc3_writel(dwc->regs, DWC3_DGCMD, cmd | DWC3_DGCMD_CMDACT);

	do {
		reg = dwc3_readl(dwc->regs, DWC3_DGCMD);
		if (!(reg & DWC3_DGCMD_CMDACT)) {
			dev_vdbg(dwc->dev, "Command Complete --> %d\n",
					DWC3_DGCMD_STATUS(reg));
			return 0;
		}

		/*
		 * We can't sleep here, because it's also called from
		 * interrupt context.
		 */
		timeout--;
		if (!timeout)
			return -ETIMEDOUT;
		udelay(1);
	} while (1);
}

int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep,
		unsigned cmd, struct dwc3_gadget_ep_cmd_params *params)
{
@@ -929,10 +956,12 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param,
	}

	dep->flags |= DWC3_EP_BUSY;

	if (start_new) {
		dep->res_trans_idx = dwc3_gadget_ep_get_transfer_index(dwc,
				dep->number);

		WARN_ON_ONCE(!dep->res_trans_idx);
	}

	return 0;
}
@@ -966,28 +995,37 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)

	list_add_tail(&req->list, &dep->request_list);

	if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && (dep->flags & DWC3_EP_BUSY))
		dep->flags |= DWC3_EP_PENDING_REQUEST;

	/*
	 * There is one special case: XferNotReady with
	 * empty list of requests. We need to kick the
	 * transfer here in that situation, otherwise
	 * we will be NAKing forever.
	 * There are two special cases:
	 *
	 * If we get XferNotReady before gadget driver
	 * has a chance to queue a request, we will ACK
	 * the IRQ but won't be able to receive the data
	 * until the next request is queued. The following
	 * code is handling exactly that.
	 * 1. XferNotReady with empty list of requests. We need to kick the
	 *    transfer here in that situation, otherwise we will be NAKing
	 *    forever. If we get XferNotReady before gadget driver has a
	 *    chance to queue a request, we will ACK the IRQ but won't be
	 *    able to receive the data until the next request is queued.
	 *    The following code is handling exactly that.
	 *
	 * 2. XferInProgress on Isoc EP with an active transfer. We need to
	 *    kick the transfer here after queuing a request, otherwise the
	 *    core may not see the modified TRB(s).
	 */
	if (dep->flags & DWC3_EP_PENDING_REQUEST) {
		int	ret;
		int start_trans;
		int	start_trans = 1;
		u8	trans_idx = dep->res_trans_idx;

		start_trans = 1;
		if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
				(dep->flags & DWC3_EP_BUSY))
				(dep->flags & DWC3_EP_BUSY)) {
			start_trans = 0;
			WARN_ON_ONCE(!trans_idx);
		} else {
			trans_idx = 0;
		}

		ret = __dwc3_gadget_kick_transfer(dep, 0, start_trans);
		ret = __dwc3_gadget_kick_transfer(dep, trans_idx, start_trans);
		if (ret && ret != -EBUSY) {
			struct dwc3	*dwc = dep->dwc;

@@ -1355,6 +1393,23 @@ static int dwc3_gadget_start(struct usb_gadget *g,

	reg = dwc3_readl(dwc->regs, DWC3_DCFG);
	reg &= ~(DWC3_DCFG_SPEED_MASK);

	/**
	 * WORKAROUND: DWC3 revision < 2.20a have an issue
	 * which would cause metastability state on Run/Stop
	 * bit if we try to force the IP to USB2-only mode.
	 *
	 * Because of that, we cannot configure the IP to any
	 * speed other than the SuperSpeed
	 *
	 * Refers to:
	 *
	 * STAR#9000525659: Clock Domain Crossing on DCTL in
	 * USB 2.0 Mode
	 */
	if (dwc->revision < DWC3_REVISION_220A)
		reg |= DWC3_DCFG_SUPERSPEED;
	else
		reg |= dwc->maximum_speed;
	dwc3_writel(dwc->regs, DWC3_DCFG, reg);

@@ -1915,6 +1970,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)

	reg = dwc3_readl(dwc->regs, DWC3_DCTL);
	reg &= ~DWC3_DCTL_TSTCTRL_MASK;
	reg &= ~(DWC3_DCTL_INITU1ENA | DWC3_DCTL_INITU2ENA);
	dwc3_writel(dwc->regs, DWC3_DCTL, reg);
	dwc->test_mode = false;

@@ -2262,8 +2318,7 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc)
		goto err1;
	}

	dwc->setup_buf = kzalloc(sizeof(*dwc->setup_buf) * 2,
			GFP_KERNEL);
	dwc->setup_buf = kzalloc(DWC3_EP0_BOUNCE_SIZE, GFP_KERNEL);
	if (!dwc->setup_buf) {
		dev_err(dwc->dev, "failed to allocate setup buffer\n");
		ret = -ENOMEM;
@@ -2271,7 +2326,8 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc)
	}

	dwc->ep0_bounce = dma_alloc_coherent(dwc->dev,
			512, &dwc->ep0_bounce_addr, GFP_KERNEL);
			DWC3_EP0_BOUNCE_SIZE, &dwc->ep0_bounce_addr,
			GFP_KERNEL);
	if (!dwc->ep0_bounce) {
		dev_err(dwc->dev, "failed to allocate ep0 bounce buffer\n");
		ret = -ENOMEM;
@@ -2312,6 +2368,14 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc)
		goto err5;
	}

	reg = dwc3_readl(dwc->regs, DWC3_DCFG);
	reg |= DWC3_DCFG_LPM_CAP;
	dwc3_writel(dwc->regs, DWC3_DCFG, reg);

	reg = dwc3_readl(dwc->regs, DWC3_DCTL);
	reg |= DWC3_DCTL_ACCEPTU1ENA | DWC3_DCTL_ACCEPTU2ENA;
	dwc3_writel(dwc->regs, DWC3_DCTL, reg);

	/* Enable all but Start and End of Frame IRQs */
	reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN |
			DWC3_DEVTEN_EVNTOVERFLOWEN |
@@ -2350,8 +2414,8 @@ err5:
	dwc3_gadget_free_endpoints(dwc);

err4:
	dma_free_coherent(dwc->dev, 512, dwc->ep0_bounce,
			dwc->ep0_bounce_addr);
	dma_free_coherent(dwc->dev, DWC3_EP0_BOUNCE_SIZE,
			dwc->ep0_bounce, dwc->ep0_bounce_addr);

err3:
	kfree(dwc->setup_buf);
@@ -2380,8 +2444,8 @@ void dwc3_gadget_exit(struct dwc3 *dwc)

	dwc3_gadget_free_endpoints(dwc);

	dma_free_coherent(dwc->dev, 512, dwc->ep0_bounce,
			dwc->ep0_bounce_addr);
	dma_free_coherent(dwc->dev, DWC3_EP0_BOUNCE_SIZE,
			dwc->ep0_bounce, dwc->ep0_bounce_addr);

	kfree(dwc->setup_buf);

Loading