[prev in list] [next in list] [prev in thread] [next in thread]
List: linux-usb
Subject: =?UTF-8?q?=5BGIT=20PULL=5D=20DWC3=20patches=20for=20next?=
From: Felipe Balbi <balbi () ti ! com>
Date: 2011-09-30 8:06:33
Message-ID: 1317369993-15724-1-git-send-email-balbi () ti ! com
[Download RAW message or body]
Hi Greg,
Here are the latest updates to DWC3 driver. With them
I have USB30CV passing all except LPM-related tests.
Driver is now a lot more stable and works fine in FS/HS/SS
modes.
Consolidated changes are appended below and patches were
sent to linux-usb a while ago for reference.
The following changes since commit 0ae52d5458ddb14d5da63054f1d8269a13fe9054:
usb: musb: Enable DMA mode1 RX for transfers without short packets (2011-09-09 13:08:17 +0300)
are available in the git repository at:
gitorious.org:usb/usb.git for-next
Felipe Balbi (9):
usb: dwc3: ep0: Make USB30CV happy with SetAddress
usb: dwc3: ep0: ignore direction on 2-stage transfer
usb: dwc3: ep0: fix debug message
usb: dwc3: gadget: add support for Bursts
usb: dwc3: gadget: implement streams support
usb: dwc3: add struct dwc3_hwparams
usb: dwc3: core: cache GHWPARAMS* registers
usb: dwc3: gadget: allow clock gating to work
usb: dwc3: convert structures into bitshifts
Paul Zimmerman (4):
usb: dwc3: gadget: fix DEPSTARTCFG for non-EP0 EPs
usb: dwc3: gadget: driver should not wait for RxFIFO to drain
usb: dwc3: gadget: make DWC3_EP_WEDGE do the right thing
usb: dwc3: gadget: fix DMA offset calculation
Sebastian Andrzej Siewior (3):
usb: dwc3: ep0: remove second giveback in error case
usb: dwc3: ep0: fix debug output
usb: dwc: remove "All rights reserved" statement.
Documentation/usb/dwc3.txt | 8 ---
drivers/usb/dwc3/core.c | 18 +++++-
drivers/usb/dwc3/core.h | 41 ++++++++++++-
drivers/usb/dwc3/debug.h | 1 -
drivers/usb/dwc3/debugfs.c | 1 -
drivers/usb/dwc3/dwc3-omap.c | 1 -
drivers/usb/dwc3/dwc3-pci.c | 1 -
drivers/usb/dwc3/ep0.c | 58 ++++++-----------
drivers/usb/dwc3/gadget.c | 115 +++++++++++++++++++++-------------
drivers/usb/dwc3/gadget.h | 140 ++++++++----------------------------------
drivers/usb/dwc3/io.h | 1 -
11 files changed, 175 insertions(+), 210 deletions(-)
diff --git a/Documentation/usb/dwc3.txt b/Documentation/usb/dwc3.txt
index 2f65853..7b590ed 100644
--- a/Documentation/usb/dwc3.txt
+++ b/Documentation/usb/dwc3.txt
@@ -3,14 +3,6 @@
~~~~~~
Please pick something while reading :)
-- Implement streaming support for BULK endpoints
- Tatyana's patch "usb: Add streams support to the gadget framework"
- introduces streaming support for the gadget driver.
- Every usb_request has new field called stream_id which holds its id.
- Every usb_ep has a field num_supported_strms which describes the max
- number of streams supported (for this ep).
- UAS is AFAIK the only gadget with streaming support.
-
- Convert interrupt handler to per-ep-thread-irq
As it turns out some DWC3-commands ~1ms to complete. Currently we spin
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 64ba097..d35f905 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -2,7 +2,6 @@
* core.c - DesignWare USB3 DRD Controller Core file
*
* Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
- * All rights reserved.
*
* Authors: Felipe Balbi <balbi@ti.com>,
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
@@ -230,6 +229,21 @@ static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
}
}
+static void __devinit dwc3_cache_hwparams(struct dwc3 *dwc)
+{
+ struct dwc3_hwparams *parms = &dwc->hwparams;
+
+ parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0);
+ parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1);
+ parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2);
+ parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3);
+ parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4);
+ parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5);
+ parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6);
+ parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7);
+ parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8);
+}
+
/**
* dwc3_core_init - Low-level initialization of DWC3 Core
* @dwc: Pointer to our controller context structure
@@ -284,6 +298,8 @@ static int __devinit dwc3_core_init(struct dwc3 *dwc)
goto err1;
}
+ dwc3_cache_hwparams(dwc);
+
return 0;
err1:
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 07d2018..29a8e16 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -2,7 +2,6 @@
* core.h - DesignWare USB3 DRD Core Header
*
* Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
- * All rights reserved.
*
* Authors: Felipe Balbi <balbi@ti.com>,
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
@@ -162,6 +161,7 @@
#define DWC3_GCTL_CORESOFTRESET (1 << 11)
#define DWC3_GCTL_SCALEDOWN(n) (n << 4)
#define DWC3_GCTL_DISSCRAMBLE (1 << 3)
+#define DWC3_GCTL_DSBLCLKGTNG (1 << 0)
/* Global USB2 PHY Configuration Register */
#define DWC3_GUSB2PHYCFG_PHYSOFTRST (1 << 31)
@@ -171,6 +171,11 @@
#define DWC3_GUSB3PIPECTL_PHYSOFTRST (1 << 31)
#define DWC3_GUSB3PIPECTL_SUSPHY (1 << 17)
+/* Global HWPARAMS1 Register */
+#define DWC3_GHWPARAMS1_EN_PWROPT(n) ((n & (3 << 24)) >> 24)
+#define DWC3_GHWPARAMS1_EN_PWROPT_NO 0
+#define DWC3_GHWPARAMS1_EN_PWROPT_CLK 1
+
/* Device Configuration Register */
#define DWC3_DCFG_DEVADDR(addr) ((addr) << 3)
#define DWC3_DCFG_DEVADDR_MASK DWC3_DCFG_DEVADDR(0x7f)
@@ -330,6 +335,7 @@ struct dwc3_event_buffer {
* @interval: the intervall on which the ISOC transfer is started
* @name: a human readable name e.g. ep1out-bulk
* @direction: true for TX, false for RX
+ * @stream_capable: true when streams are enabled
*/
struct dwc3_ep {
struct usb_ep endpoint;
@@ -363,6 +369,7 @@ struct dwc3_ep {
char name[20];
unsigned direction:1;
+ unsigned stream_capable:1;
};
enum dwc3_phy {
@@ -506,6 +513,30 @@ static inline void dwc3_trb_to_nat(struct dwc3_trb_hw *hw, struct dwc3_trb *nat)
}
/**
+ * dwc3_hwparams - copy of HWPARAMS registers
+ * @hwparams0 - GHWPARAMS0
+ * @hwparams1 - GHWPARAMS1
+ * @hwparams2 - GHWPARAMS2
+ * @hwparams3 - GHWPARAMS3
+ * @hwparams4 - GHWPARAMS4
+ * @hwparams5 - GHWPARAMS5
+ * @hwparams6 - GHWPARAMS6
+ * @hwparams7 - GHWPARAMS7
+ * @hwparams8 - GHWPARAMS8
+ */
+struct dwc3_hwparams {
+ u32 hwparams0;
+ u32 hwparams1;
+ u32 hwparams2;
+ u32 hwparams3;
+ u32 hwparams4;
+ u32 hwparams5;
+ u32 hwparams6;
+ u32 hwparams7;
+ u32 hwparams8;
+};
+
+/**
* struct dwc3 - representation of our controller
* @ctrl_req: usb control request which is used for ep0
* @ep0_trb: trb which is used for the ctrl_req
@@ -530,11 +561,13 @@ static inline void dwc3_trb_to_nat(struct dwc3_trb_hw *hw, struct dwc3_trb *nat)
* @ep0_status_pending: ep0 status response without a req is pending
* @ep0_bounced: true when we used bounce buffer
* @ep0_expect_in: true when we expect a DATA IN transfer
+ * @start_config_issued: true when StartConfig command has been issued
* @ep0_next_event: hold the next expected event
* @ep0state: state of endpoint zero
* @link_state: link state
* @speed: device speed (super, high, full, low)
* @mem: points to start of memory which is used for this struct.
+ * @hwparams: copy of hwparams registers
* @root: debugfs root folder pointer
*/
struct dwc3 {
@@ -577,6 +610,7 @@ struct dwc3 {
unsigned ep0_status_pending:1;
unsigned ep0_bounced:1;
unsigned ep0_expect_in:1;
+ unsigned start_config_issued:1;
enum dwc3_ep0_next ep0_next_event;
enum dwc3_ep0_state ep0state;
@@ -586,6 +620,7 @@ struct dwc3 {
u8 speed;
void *mem;
+ struct dwc3_hwparams hwparams;
struct dentry *root;
};
@@ -649,6 +684,10 @@ struct dwc3_event_depevt {
#define DEPEVT_STATUS_IOC (1 << 2)
#define DEPEVT_STATUS_LST (1 << 3)
+/* Stream event only */
+#define DEPEVT_STREAMEVT_FOUND 1
+#define DEPEVT_STREAMEVT_NOTFOUND 2
+
/* Control-only Status */
#define DEPEVT_STATUS_CONTROL_SETUP 0
#define DEPEVT_STATUS_CONTROL_DATA 1
diff --git a/drivers/usb/dwc3/debug.h b/drivers/usb/dwc3/debug.h
index ee3ba73..5894ee8 100644
--- a/drivers/usb/dwc3/debug.h
+++ b/drivers/usb/dwc3/debug.h
@@ -2,7 +2,6 @@
* debug.h - DesignWare USB3 DRD Controller Debug Header
*
* Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
- * All rights reserved.
*
* Authors: Felipe Balbi <balbi@ti.com>,
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c
index 20d329f..da1ad77 100644
--- a/drivers/usb/dwc3/debugfs.c
+++ b/drivers/usb/dwc3/debugfs.c
@@ -2,7 +2,6 @@
* debugfs.c - DesignWare USB3 DRD Controller DebugFS file
*
* Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
- * All rights reserved.
*
* Authors: Felipe Balbi <balbi@ti.com>,
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
index 72cc92b..64ce3fc 100644
--- a/drivers/usb/dwc3/dwc3-omap.c
+++ b/drivers/usb/dwc3/dwc3-omap.c
@@ -2,7 +2,6 @@
* dwc3-omap.c - OMAP Specific Glue layer
*
* Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
- * All rights reserved.
*
* Authors: Felipe Balbi <balbi@ti.com>,
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
index e3b77d2..f77c000 100644
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -2,7 +2,6 @@
* dwc3-pci.c - PCI Specific glue layer
*
* Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
- * All rights reserved.
*
* Authors: Felipe Balbi <balbi@ti.com>,
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index b66d969..69a4e43 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -2,7 +2,6 @@
* ep0.c - DesignWare USB3 DRD Controller Endpoint 0 Handling
*
* Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
- * All rights reserved.
*
* Authors: Felipe Balbi <balbi@ti.com>,
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
@@ -104,10 +103,8 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
dwc3_trb_to_hw(&trb, trb_hw);
memset(¶ms, 0, sizeof(params));
- params.param0.depstrtxfer.transfer_desc_addr_high =
- upper_32_bits(dwc->ep0_trb_addr);
- params.param1.depstrtxfer.transfer_desc_addr_low =
- lower_32_bits(dwc->ep0_trb_addr);
+ params.param0 = upper_32_bits(dwc->ep0_trb_addr);
+ params.param1 = lower_32_bits(dwc->ep0_trb_addr);
ret = dwc3_send_gadget_ep_cmd(dwc, dep->number,
DWC3_DEPCMD_STARTTRANSFER, ¶ms);
@@ -421,7 +418,6 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
{
- int ret = 0;
u32 addr;
u32 reg;
@@ -429,29 +425,17 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
if (addr > 127)
return -EINVAL;
- switch (dwc->dev_state) {
- case DWC3_DEFAULT_STATE:
- case DWC3_ADDRESS_STATE:
- /*
- * Not sure if we should program DevAddr now or later
- */
- reg = dwc3_readl(dwc->regs, DWC3_DCFG);
- reg &= ~(DWC3_DCFG_DEVADDR_MASK);
- reg |= DWC3_DCFG_DEVADDR(addr);
- dwc3_writel(dwc->regs, DWC3_DCFG, reg);
-
- if (addr)
- dwc->dev_state = DWC3_ADDRESS_STATE;
- else
- dwc->dev_state = DWC3_DEFAULT_STATE;
- break;
+ reg = dwc3_readl(dwc->regs, DWC3_DCFG);
+ reg &= ~(DWC3_DCFG_DEVADDR_MASK);
+ reg |= DWC3_DCFG_DEVADDR(addr);
+ dwc3_writel(dwc->regs, DWC3_DCFG, reg);
- case DWC3_CONFIGURED_STATE:
- ret = -EINVAL;
- break;
- }
+ if (addr)
+ dwc->dev_state = DWC3_ADDRESS_STATE;
+ else
+ dwc->dev_state = DWC3_DEFAULT_STATE;
- return ret;
+ return 0;
}
static int dwc3_ep0_delegate_req(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
@@ -469,6 +453,7 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
u32 cfg;
int ret;
+ dwc->start_config_issued = false;
cfg = le16_to_cpu(ctrl->wValue);
switch (dwc->dev_state) {
@@ -538,15 +523,15 @@ static void dwc3_ep0_inspect_setup(struct dwc3 *dwc,
len = le16_to_cpu(ctrl->wLength);
if (!len) {
- dwc->three_stage_setup = 0;
+ dwc->three_stage_setup = false;
+ dwc->ep0_expect_in = false;
dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS;
} else {
- dwc->three_stage_setup = 1;
+ dwc->three_stage_setup = true;
+ dwc->ep0_expect_in = !!(ctrl->bRequestType & USB_DIR_IN);
dwc->ep0_next_event = DWC3_EP0_NRDY_DATA;
}
- dwc->ep0_expect_in = !!(ctrl->bRequestType & USB_DIR_IN);
-
if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD)
ret = dwc3_ep0_std_request(dwc, ctrl);
else
@@ -600,7 +585,6 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
/* for some reason we did not get everything out */
dwc3_ep0_stall_and_restart(dwc);
- dwc3_gadget_giveback(dep, r, -ECONNRESET);
} else {
/*
* handle the case where we have to send a zero packet. This
@@ -753,8 +737,8 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
if (dwc->ep0_next_event != DWC3_EP0_NRDY_DATA) {
dev_vdbg(dwc->dev, "Expected %d got %d\n",
- DEPEVT_STATUS_CONTROL_DATA,
- event->status);
+ dwc->ep0_next_event,
+ DWC3_EP0_NRDY_DATA);
dwc3_ep0_stall_and_restart(dwc);
return;
@@ -782,8 +766,8 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
if (dwc->ep0_next_event != DWC3_EP0_NRDY_STATUS) {
dev_vdbg(dwc->dev, "Expected %d got %d\n",
- DEPEVT_STATUS_CONTROL_STATUS,
- event->status);
+ dwc->ep0_next_event,
+ DWC3_EP0_NRDY_STATUS);
dwc3_ep0_stall_and_restart(dwc);
return;
@@ -799,7 +783,7 @@ void dwc3_ep0_interrupt(struct dwc3 *dwc,
dev_dbg(dwc->dev, "%s while ep%d%s in state '%s'\n",
dwc3_ep_event_string(event->endpoint_event),
- epnum, (epnum & 1) ? "in" : "out",
+ epnum >> 1, (epnum & 1) ? "in" : "out",
dwc3_ep0_state_string(dwc->ep0state));
switch (event->endpoint_event) {
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 859257a..fa824cf 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2,7 +2,6 @@
* gadget.c - DesignWare USB3 DRD Controller Gadget Framework Link
*
* Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
- * All rights reserved.
*
* Authors: Felipe Balbi <balbi@ti.com>,
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
@@ -159,12 +158,12 @@ int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep,
dev_vdbg(dwc->dev, "%s: cmd '%s' params %08x %08x %08x\n",
dep->name,
- dwc3_gadget_ep_cmd_string(cmd), params->param0.raw,
- params->param1.raw, params->param2.raw);
+ dwc3_gadget_ep_cmd_string(cmd), params->param0,
+ params->param1, params->param2);
- dwc3_writel(dwc->regs, DWC3_DEPCMDPAR0(ep), params->param0.raw);
- dwc3_writel(dwc->regs, DWC3_DEPCMDPAR1(ep), params->param1.raw);
- dwc3_writel(dwc->regs, DWC3_DEPCMDPAR2(ep), params->param2.raw);
+ dwc3_writel(dwc->regs, DWC3_DEPCMDPAR0(ep), params->param0);
+ dwc3_writel(dwc->regs, DWC3_DEPCMDPAR1(ep), params->param1);
+ dwc3_writel(dwc->regs, DWC3_DEPCMDPAR2(ep), params->param2);
dwc3_writel(dwc->regs, DWC3_DEPCMD(ep), cmd | DWC3_DEPCMD_CMDACT);
do {
@@ -190,7 +189,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep,
static dma_addr_t dwc3_trb_dma_offset(struct dwc3_ep *dep,
struct dwc3_trb_hw *trb)
{
- u32 offset = trb - dep->trb_pool;
+ u32 offset = (char *) trb - (char *) dep->trb_pool;
return dep->trb_pool_dma + offset;
}
@@ -238,8 +237,12 @@ static int dwc3_gadget_start_config(struct dwc3 *dwc, struct dwc3_ep *dep)
if (dep->number != 1) {
cmd = DWC3_DEPCMD_DEPSTARTCFG;
/* XferRscIdx == 0 for ep0 and 2 for the remaining */
- if (dep->number > 1)
+ if (dep->number > 1) {
+ if (dwc->start_config_issued)
+ return 0;
+ dwc->start_config_issued = true;
cmd |= DWC3_DEPCMD_PARAM(2);
+ }
return dwc3_send_gadget_ep_cmd(dwc, 0, cmd, ¶ms);
}
@@ -254,14 +257,21 @@ static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep,
memset(¶ms, 0x00, sizeof(params));
- params.param0.depcfg.ep_type = usb_endpoint_type(desc);
- params.param0.depcfg.max_packet_size = usb_endpoint_maxp(desc);
+ params.param0 = DWC3_DEPCFG_EP_TYPE(usb_endpoint_type(desc))
+ | DWC3_DEPCFG_MAX_PACKET_SIZE(usb_endpoint_maxp(desc))
+ | DWC3_DEPCFG_BURST_SIZE(dep->endpoint.maxburst);
+
+ params.param1 = DWC3_DEPCFG_XFER_COMPLETE_EN
+ | DWC3_DEPCFG_XFER_NOT_READY_EN;
- params.param1.depcfg.xfer_complete_enable = true;
- params.param1.depcfg.xfer_not_ready_enable = true;
+ if (usb_endpoint_xfer_bulk(desc) && dep->endpoint.max_streams) {
+ params.param1 |= DWC3_DEPCFG_STREAM_CAPABLE
+ | DWC3_DEPCFG_STREAM_EVENT_EN;
+ dep->stream_capable = true;
+ }
if (usb_endpoint_xfer_isoc(desc))
- params.param1.depcfg.xfer_in_progress_enable = true;
+ params.param1 |= DWC3_DEPCFG_XFER_IN_PROGRESS_EN;
/*
* We are doing 1:1 mapping for endpoints, meaning
@@ -269,17 +279,17 @@ static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep,
* so on. We consider the direction bit as part of the physical
* endpoint number. So USB endpoint 0x81 is 0x03.
*/
- params.param1.depcfg.ep_number = dep->number;
+ params.param1 |= DWC3_DEPCFG_EP_NUMBER(dep->number);
/*
* We must use the lower 16 TX FIFOs even though
* HW might have more
*/
if (dep->direction)
- params.param0.depcfg.fifo_number = dep->number >> 1;
+ params.param0 |= DWC3_DEPCFG_FIFO_NUMBER(dep->number >> 1);
if (desc->bInterval) {
- params.param1.depcfg.binterval_m1 = desc->bInterval - 1;
+ params.param1 |= DWC3_DEPCFG_BINTERVAL_M1(desc->bInterval - 1);
dep->interval = 1 << (desc->bInterval - 1);
}
@@ -293,7 +303,7 @@ static int dwc3_gadget_set_xfer_resource(struct dwc3 *dwc, struct dwc3_ep *dep)
memset(¶ms, 0x00, sizeof(params));
- params.param0.depxfercfg.number_xfer_resources = 1;
+ params.param0 = DWC3_DEPXFERCFG_NUM_XFER_RES(1);
return dwc3_send_gadget_ep_cmd(dwc, dep->number,
DWC3_DEPCMD_SETTRANSFRESOURCE, ¶ms);
@@ -387,15 +397,16 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
struct dwc3 *dwc = dep->dwc;
u32 reg;
- dep->flags &= ~DWC3_EP_ENABLED;
dwc3_remove_requests(dwc, dep);
reg = dwc3_readl(dwc->regs, DWC3_DALEPENA);
reg &= ~DWC3_DALEPENA_EP(dep->number);
dwc3_writel(dwc->regs, DWC3_DALEPENA, reg);
+ dep->stream_capable = false;
dep->desc = NULL;
dep->type = 0;
+ dep->flags = 0;
return 0;
}
@@ -629,6 +640,9 @@ static struct dwc3_request *dwc3_prepare_trbs(struct dwc3_ep *dep,
trb.lst = last_one;
}
+ if (usb_endpoint_xfer_bulk(dep->desc) && dep->stream_capable)
+ trb.sid_sofn = req->request.stream_id;
+
switch (usb_endpoint_type(dep->desc)) {
case USB_ENDPOINT_XFER_CONTROL:
trb.trbctl = DWC3_TRBCTL_CONTROL_SETUP;
@@ -705,10 +719,8 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param,
}
memset(¶ms, 0, sizeof(params));
- params.param0.depstrtxfer.transfer_desc_addr_high =
- upper_32_bits(req->trb_dma);
- params.param1.depstrtxfer.transfer_desc_addr_low =
- lower_32_bits(req->trb_dma);
+ params.param0 = upper_32_bits(req->trb_dma);
+ params.param1 = lower_32_bits(req->trb_dma);
if (start_new)
cmd = DWC3_DEPCMD_STARTTRANSFER;
@@ -891,6 +903,9 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value)
else
dep->flags |= DWC3_EP_STALL;
} else {
+ if (dep->flags & DWC3_EP_WEDGE)
+ return 0;
+
ret = dwc3_send_gadget_ep_cmd(dwc, dep->number,
DWC3_DEPCMD_CLEARSTALL, ¶ms);
if (ret)
@@ -900,6 +915,7 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value)
else
dep->flags &= ~DWC3_EP_STALL;
}
+
return ret;
}
@@ -933,7 +949,7 @@ static int dwc3_gadget_ep_set_wedge(struct usb_ep *ep)
dep->flags |= DWC3_EP_WEDGE;
- return usb_ep_set_halt(ep);
+ return dwc3_gadget_ep_set_halt(ep, 1);
}
/* -------------------------------------------------------------------------- */
@@ -1146,6 +1162,14 @@ static int dwc3_gadget_start(struct usb_gadget *g,
reg &= ~DWC3_GCTL_DISSCRAMBLE;
reg |= DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_DEVICE);
+ switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams0)) {
+ case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
+ reg &= ~DWC3_GCTL_DSBLCLKGTNG;
+ break;
+ default:
+ dev_dbg(dwc->dev, "No power optimization available\n");
+ }
+
/*
* WORKAROUND: DWC3 revisions <1.90a have a bug
* when The device fails to connect at SuperSpeed
@@ -1162,6 +1186,8 @@ static int dwc3_gadget_start(struct usb_gadget *g,
reg |= DWC3_DCFG_SUPERSPEED;
dwc3_writel(dwc->regs, DWC3_DCFG, reg);
+ dwc->start_config_issued = false;
+
/* Start with SuperSpeed Default */
dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
@@ -1495,12 +1521,28 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
}
break;
+ case DWC3_DEPEVT_STREAMEVT:
+ if (!usb_endpoint_xfer_bulk(dep->desc)) {
+ dev_err(dwc->dev, "Stream event for non-Bulk %s\n",
+ dep->name);
+ return;
+ }
+
+ switch (event->status) {
+ case DEPEVT_STREAMEVT_FOUND:
+ dev_vdbg(dwc->dev, "Stream %d found and started\n",
+ event->parameters);
+
+ break;
+ case DEPEVT_STREAMEVT_NOTFOUND:
+ /* FALLTHROUGH */
+ default:
+ dev_dbg(dwc->dev, "Couldn't find suitable stream\n");
+ }
+ break;
case DWC3_DEPEVT_RXTXFIFOEVT:
dev_dbg(dwc->dev, "%s FIFO Overrun\n", dep->name);
break;
- case DWC3_DEPEVT_STREAMEVT:
- dev_dbg(dwc->dev, "%s Stream Event\n", dep->name);
- break;
case DWC3_DEPEVT_EPCMDCMPLT:
dwc3_ep_cmd_compl(dep, event);
break;
@@ -1593,6 +1635,7 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc)
dwc3_stop_active_transfers(dwc);
dwc3_disconnect_gadget(dwc);
+ dwc->start_config_issued = false;
dwc->gadget.speed = USB_SPEED_UNKNOWN;
}
@@ -1644,30 +1687,12 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
dwc3_stop_active_transfers(dwc);
dwc3_clear_stall_all_ep(dwc);
+ dwc->start_config_issued = false;
/* Reset device address to zero */
reg = dwc3_readl(dwc->regs, DWC3_DCFG);
reg &= ~(DWC3_DCFG_DEVADDR_MASK);
dwc3_writel(dwc->regs, DWC3_DCFG, reg);
-
- /*
- * Wait for RxFifo to drain
- *
- * REVISIT probably shouldn't wait forever.
- * In case Hardware ends up in a screwed up
- * case, we error out, notify the user and,
- * maybe, WARN() or BUG() but leave the rest
- * of the kernel working fine.
- *
- * REVISIT the below is rather CPU intensive,
- * maybe we should read and if it doesn't work
- * sleep (not busy wait) for a few useconds.
- *
- * REVISIT why wait until the RXFIFO is empty anyway?
- */
- while (!(dwc3_readl(dwc->regs, DWC3_DSTS)
- & DWC3_DSTS_RXFIFOEMPTY))
- cpu_relax();
}
static void dwc3_update_ram_clk_sel(struct dwc3 *dwc, u32 speed)
diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h
index 4809ac8..71145a4 100644
--- a/drivers/usb/dwc3/gadget.h
+++ b/drivers/usb/dwc3/gadget.h
@@ -2,7 +2,6 @@
* gadget.h - DesignWare USB3 DRD Gadget Header
*
* Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
- * All rights reserved.
*
* Authors: Felipe Balbi <balbi@ti.com>,
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
@@ -48,120 +47,35 @@ struct dwc3;
#define to_dwc3_ep(ep) (container_of(ep, struct dwc3_ep, endpoint))
#define gadget_to_dwc(g) (container_of(g, struct dwc3, gadget))
-/**
- * struct dwc3_gadget_ep_depcfg_param1 - DEPCMDPAR0 for DEPCFG command
- * @interrupt_number: self-explanatory
- * @reserved7_5: set to zero
- * @xfer_complete_enable: event generated when transfer completed
- * @xfer_in_progress_enable: event generated when transfer in progress
- * @xfer_not_ready_enable: event generated when transfer not read
- * @fifo_error_enable: generates events when FIFO Underrun (IN eps)
- * or FIFO Overrun (OUT) eps
- * @reserved_12: set to zero
- * @stream_event_enable: event generated on stream
- * @reserved14_15: set to zero
- * @binterval_m1: bInterval minus 1
- * @stream_capable: this EP is capable of handling streams
- * @ep_number: self-explanatory
- * @bulk_based: Set to ‘1' if this isochronous endpoint represents a bulk
- * data stream that ignores the relationship of bus time to the
- * intervals programmed in TRBs.
- * @fifo_based: Set to ‘1' if this isochronous endpoint represents a
- * FIFO-based data stream where TRBs have fixed values and are never
- * written back by the core.
- */
-struct dwc3_gadget_ep_depcfg_param1 {
- u32 interrupt_number:5;
- u32 reserved7_5:3; /* set to zero */
- u32 xfer_complete_enable:1;
- u32 xfer_in_progress_enable:1;
- u32 xfer_not_ready_enable:1;
- u32 fifo_error_enable:1; /* IN-underrun, OUT-overrun */
- u32 reserved12:1; /* set to zero */
- u32 stream_event_enable:1;
- u32 reserved14_15:2;
- u32 binterval_m1:8; /* bInterval minus 1 */
- u32 stream_capable:1;
- u32 ep_number:5;
- u32 bulk_based:1;
- u32 fifo_based:1;
-} __packed;
-
-/**
- * struct dwc3_gadget_ep_depcfg_param0 - Parameter 0 for DEPCFG
- * @reserved0: set to zero
- * @ep_type: Endpoint Type (control, bulk, iso, interrupt)
- * @max_packet_size: max packet size in bytes
- * @reserved16_14: set to zero
- * @fifo_number: self-explanatory
- * @burst_size: burst size minus 1
- * @data_sequence_number: Must be 0 when an endpoint is initially configured
- * May be non-zero when an endpoint is configured after a power transition
- * that requires a save/restore.
- * @ignore_sequence_number: Set to ‘1' to avoid resetting the sequence
- * number. This setting is used by software to modify the DEPEVTEN
- * event enable bits without modifying other endpoint settings.
- */
-struct dwc3_gadget_ep_depcfg_param0 {
- u32 reserved0:1;
- u32 ep_type:2;
- u32 max_packet_size:11;
- u32 reserved16_14:3;
- u32 fifo_number:5;
- u32 burst_size:4;
- u32 data_sequence_number:5;
- u32 ignore_sequence_number:1;
-} __packed;
-
-/**
- * struct dwc3_gadget_ep_depxfercfg_param0 - Parameter 0 of DEPXFERCFG
- * @number_xfer_resources: Defines the number of Transfer Resources allocated
- * to this endpoint. This field must be set to 1.
- * @reserved16_31: set to zero;
- */
-struct dwc3_gadget_ep_depxfercfg_param0 {
- u32 number_xfer_resources:16;
- u32 reserved16_31:16;
-} __packed;
-
-/**
- * struct dwc3_gadget_ep_depstrtxfer_param1 - Parameter 1 of DEPSTRTXFER
- * @transfer_desc_addr_low: Indicates the lower 32 bits of the external
- * memory's start address for the transfer descriptor. Because TRBs
- * must be aligned to a 16-byte boundary, the lower 4 bits of this
- * address must be 0.
- */
-struct dwc3_gadget_ep_depstrtxfer_param1 {
- u32 transfer_desc_addr_low;
-} __packed;
-
-/**
- * struct dwc3_gadget_ep_depstrtxfer_param1 - Parameter 1 of DEPSTRTXFER
- * @transfer_desc_addr_high: Indicates the higher 32 bits of the external
- * memory's start address for the transfer descriptor.
- */
-struct dwc3_gadget_ep_depstrtxfer_param0 {
- u32 transfer_desc_addr_high;
-} __packed;
+/* DEPCFG parameter 1 */
+#define DWC3_DEPCFG_INT_NUM(n) ((n) << 0)
+#define DWC3_DEPCFG_XFER_COMPLETE_EN (1 << 8)
+#define DWC3_DEPCFG_XFER_IN_PROGRESS_EN (1 << 9)
+#define DWC3_DEPCFG_XFER_NOT_READY_EN (1 << 10)
+#define DWC3_DEPCFG_FIFO_ERROR_EN (1 << 11)
+#define DWC3_DEPCFG_STREAM_EVENT_EN (1 << 13)
+#define DWC3_DEPCFG_BINTERVAL_M1(n) ((n) << 16)
+#define DWC3_DEPCFG_STREAM_CAPABLE (1 << 24)
+#define DWC3_DEPCFG_EP_NUMBER(n) ((n) << 25)
+#define DWC3_DEPCFG_BULK_BASED (1 << 30)
+#define DWC3_DEPCFG_FIFO_BASED (1 << 31)
+
+/* DEPCFG parameter 0 */
+#define DWC3_DEPCFG_EP_TYPE(n) ((n) << 1)
+#define DWC3_DEPCFG_MAX_PACKET_SIZE(n) ((n) << 3)
+#define DWC3_DEPCFG_FIFO_NUMBER(n) ((n) << 17)
+#define DWC3_DEPCFG_BURST_SIZE(n) ((n) << 22)
+#define DWC3_DEPCFG_DATA_SEQ_NUM(n) ((n) << 26)
+#define DWC3_DEPCFG_IGN_SEQ_NUM (1 << 31)
+
+/* DEPXFERCFG parameter 0 */
+#define DWC3_DEPXFERCFG_NUM_XFER_RES(n) ((n) & 0xffff)
struct dwc3_gadget_ep_cmd_params {
- union {
- u32 raw;
- } param2;
-
- union {
- u32 raw;
- struct dwc3_gadget_ep_depcfg_param1 depcfg;
- struct dwc3_gadget_ep_depstrtxfer_param1 depstrtxfer;
- } param1;
-
- union {
- u32 raw;
- struct dwc3_gadget_ep_depcfg_param0 depcfg;
- struct dwc3_gadget_ep_depxfercfg_param0 depxfercfg;
- struct dwc3_gadget_ep_depstrtxfer_param0 depstrtxfer;
- } param0;
-} __packed;
+ u32 param2;
+ u32 param1;
+ u32 param0;
+};
/* -------------------------------------------------------------------------- */
diff --git a/drivers/usb/dwc3/io.h b/drivers/usb/dwc3/io.h
index 0c4e2a9..bc957db 100644
--- a/drivers/usb/dwc3/io.h
+++ b/drivers/usb/dwc3/io.h
@@ -2,7 +2,6 @@
* io.h - DesignWare USB3 DRD IO Header
*
* Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
- * All rights reserved.
*
* Authors: Felipe Balbi <balbi@ti.com>,
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic