From 1522d7034d739f2d348f4c544fe12ff9627c36a4 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 23 Mar 2012 12:10:48 +0200 Subject: usb: dwc3: core: define more revision macros We have other revisions already released, let's define revision macros for those so we can do runtime detection of known erratas. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 6c7945b4cad..a32c2b503fe 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -609,6 +609,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; -- cgit v1.2.3-70-g09d2 From 07e7f47b6d8da3e290f90615c9a74dff0115709e Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 23 Mar 2012 12:20:31 +0200 Subject: usb: dwc3: workaround: metastability state on Run/Stop bit All revisions prior to 2.20a have a known issue which causes metastability state on Run/Stop bit if we configure the core to work on any of the USB2-only speeds. The suggested workaround is just to never configure the core to anything other than SuperSpeed. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 5255fe975ea..dda56b8f861 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1356,7 +1356,24 @@ static int dwc3_gadget_start(struct usb_gadget *g, reg = dwc3_readl(dwc->regs, DWC3_DCFG); reg &= ~(DWC3_DCFG_SPEED_MASK); - reg |= dwc->maximum_speed; + + /** + * 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); dwc->start_config_issued = false; -- cgit v1.2.3-70-g09d2 From ab5e59dbdb6d2e2d784381bd194e0229b8b990b5 Mon Sep 17 00:00:00 2001 From: Ido Shayevitz Date: Tue, 24 Apr 2012 14:18:38 +0300 Subject: usb: dwc3: omap: add dwc3_omap_readl/writel functions We separate between dwc3-omap helper functions to dwc3-core helper functions. This will allow us to change the helper functions implementation according to each module need. Signed-off-by: Ido Shayevitz Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-omap.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index d7d9c0ec951..479dc047da3 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -49,7 +49,6 @@ #include #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); -- cgit v1.2.3-70-g09d2 From 51249dca627d9d0e6b41531e716cbc308554a62c Mon Sep 17 00:00:00 2001 From: Ido Shayevitz Date: Tue, 24 Apr 2012 14:18:39 +0300 Subject: usb: dwc3: core: split host address space This fix prevents a problem with dwc3 and host mode where we were requesting the entire memory region in dwc3/core.c, thus preventing xhci-plat from ever ioremapping its own address space. Signed-off-by: Ido Shayevitz Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 31 ++++++++++++++++++------------- drivers/usb/dwc3/core.h | 15 ++++++++++++--- drivers/usb/dwc3/host.c | 19 ++----------------- drivers/usb/dwc3/io.h | 16 ++++++++++++++-- 4 files changed, 46 insertions(+), 35 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 7bd815a507e..b2b41722369 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -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 = devm_request_mem_region(dev, res->start, resource_size(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; + + /* + * 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; diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index a32c2b503fe..c7b3ca037bb 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -52,6 +52,7 @@ /* Global constants */ #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 +76,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 @@ -583,7 +594,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]; @@ -594,8 +605,6 @@ struct dwc3 { void __iomem *regs; size_t regs_size; - int irq; - u32 num_event_buffers; u32 u1u2; u32 maximum_speed; diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c index b108d18fd40..56a62342884 100644 --- a/drivers/usb/dwc3/host.c +++ b/drivers/usb/dwc3/host.c @@ -39,15 +39,6 @@ #include "core.h" -static struct resource generic_resources[] = { - { - .flags = IORESOURCE_IRQ, - }, - { - .flags = IORESOURCE_MEM, - }, -}; - int dwc3_host_init(struct dwc3 *dwc) { struct platform_device *xhci; @@ -68,14 +59,8 @@ int dwc3_host_init(struct dwc3 *dwc) dwc->xhci = xhci; - /* setup resources */ - generic_resources[0].start = dwc->irq; - - generic_resources[1].start = dwc->res->start; - generic_resources[1].end = dwc->res->start + 0x7fff; - - ret = platform_device_add_resources(xhci, generic_resources, - ARRAY_SIZE(generic_resources)); + ret = platform_device_add_resources(xhci, dwc->xhci_resources, + DWC3_XHCI_RESOURCES_NUM); if (ret) { dev_err(dwc->dev, "couldn't add resources to xHCI device\n"); goto err1; diff --git a/drivers/usb/dwc3/io.h b/drivers/usb/dwc3/io.h index 071d561f3e6..a50f76b9d19 100644 --- a/drivers/usb/dwc3/io.h +++ b/drivers/usb/dwc3/io.h @@ -41,14 +41,26 @@ #include +#include "core.h" + static inline u32 dwc3_readl(void __iomem *base, u32 offset) { - return readl(base + offset); + /* + * We requested the mem region starting from the Globals address + * space, see dwc3_probe in core.c. + * However, the offsets are given starting from xHCI address space. + */ + return readl(base + (offset - DWC3_GLOBALS_REGS_START)); } static inline void dwc3_writel(void __iomem *base, u32 offset, u32 value) { - writel(value, base + offset); + /* + * We requested the mem region starting from the Globals address + * space, see dwc3_probe in core.c. + * However, the offsets are given starting from xHCI address space. + */ + writel(value, base + (offset - DWC3_GLOBALS_REGS_START)); } #endif /* __DRIVERS_USB_DWC3_IO_H */ -- cgit v1.2.3-70-g09d2 From e6a3b5e2888b51e37c65c97dae966f793bc4806a Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 13 Sep 2011 17:54:39 +0200 Subject: usb: dwc3: ep0: add LPM handling On device loading the driver enables LPM and the acceptance of U1 and U2 states. The [Set|Clear]Feature requests for "U1/U2" are forwarded directly to the hardware and allow / forbid the initiation of the low power links. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 1 + drivers/usb/dwc3/ep0.c | 46 +++++++++++++++++++++++++++++++++++----------- drivers/usb/dwc3/gadget.c | 9 +++++++++ 3 files changed, 45 insertions(+), 11 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index c7b3ca037bb..93f9973ad53 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -194,6 +194,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) diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 25910e251c0..18494b0d7d6 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -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: diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index dda56b8f861..906db570ef4 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1933,6 +1933,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; @@ -2330,6 +2331,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 | -- cgit v1.2.3-70-g09d2 From b09bb64239c83113b8b35fa6a1ecae43d8297eaa Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 24 Apr 2012 16:19:11 +0300 Subject: usb: dwc3: gadget: implement Global Command support This will be used by the ep0 layer for implementing Set SEL Standard Request. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 6 ++++-- drivers/usb/dwc3/gadget.c | 27 +++++++++++++++++++++++++++ drivers/usb/dwc3/gadget.h | 1 + 3 files changed, 32 insertions(+), 2 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 93f9973ad53..42641ada9e2 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -284,12 +284,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) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 906db570ef4..158d396d0d0 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -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) { diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h index a8600084348..95ef6a2f776 100644 --- a/drivers/usb/dwc3/gadget.h +++ b/drivers/usb/dwc3/gadget.h @@ -111,6 +111,7 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value); int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep, unsigned cmd, struct dwc3_gadget_ep_cmd_params *params); +int dwc3_send_gadget_generic_command(struct dwc3 *dwc, int cmd, u32 param); /** * dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW -- cgit v1.2.3-70-g09d2 From 865e09e71622f92a46b47019500632bf5bc010a8 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 24 Apr 2012 16:19:49 +0300 Subject: usb: dwc3: ep0: implement Set SEL support This patch implements Set SEL Standard Request support for dwc3 driver. It needs to issue a command to the controller passing the timing we received on the data phase of the Set SEL request. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 10 ++++++ drivers/usb/dwc3/ep0.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 42641ada9e2..39fbd154dc1 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -575,6 +575,10 @@ 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. + * @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 @@ -641,7 +645,13 @@ struct dwc3 { enum dwc3_link_state link_state; enum dwc3_device_state dev_state; + u16 u2sel; + u16 u2pel; + u8 u1sel; + u8 u1pel; + u8 speed; + void *mem; struct dwc3_hwparams hwparams; diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 18494b0d7d6..9683d98bbb5 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -490,6 +490,85 @@ 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_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) { int ret; @@ -515,6 +594,10 @@ 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; default: dev_vdbg(dwc->dev, "Forwarding to gadget driver\n"); ret = dwc3_ep0_delegate_req(dwc, ctrl); -- cgit v1.2.3-70-g09d2 From 7ed6d227c3d29e156f7affbad4d4679d1e409ef2 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 25 Apr 2012 14:13:09 +0300 Subject: usb: dwc3: gadget: increase setup buffer size We want to re-use that buffer for other USB requests, so let's increase it to biggest wMaxPacketSize for ep0 so it works for everything we have in mind. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 158d396d0d0..49ee83ed68b 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2308,8 +2308,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(512, GFP_KERNEL); if (!dwc->setup_buf) { dev_err(dwc->dev, "failed to allocate setup buffer\n"); ret = -ENOMEM; -- cgit v1.2.3-70-g09d2 From c12a0d862a900707cdc683efad39d05697d9964d Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 25 Apr 2012 10:45:05 +0300 Subject: usb: dwc3: ep0: implement support for Set Isoch Delay request This is basically a noop for DWC3. We don't have to do anything. Basically we test if the request parameters are correct, cache the Isochronous Delay and return success. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 2 ++ drivers/usb/dwc3/ep0.c | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 39fbd154dc1..ef28bd5680c 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -575,6 +575,7 @@ 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. @@ -645,6 +646,7 @@ struct dwc3 { enum dwc3_link_state link_state; enum dwc3_device_state dev_state; + u16 isoch_delay; u16 u2sel; u16 u2pel; u8 u1sel; diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 9683d98bbb5..8d41b6a6192 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -569,6 +569,28 @@ static int dwc3_ep0_set_sel(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) 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; @@ -598,6 +620,10 @@ static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) 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); -- cgit v1.2.3-70-g09d2 From f898ae09a043cf9c3c4be82c04e08fcf00fe82c1 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Thu, 29 Mar 2012 18:16:54 +0000 Subject: usb: dwc3: gadget: issue Update Transfer command after queuing isoc request Issue an Update Transfer command after queuing a request to an isoc EP with an active transfer. This is required according to the dwc3 databook. Pratyush Anand reports that this fixes a problem he was having with Isoc IN transfers. Tested-by: Pratyush Anand Signed-off-by: Paul Zimmerman Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 49ee83ed68b..31ffc5c2735 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -957,10 +957,12 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param, } dep->flags |= DWC3_EP_BUSY; - dep->res_trans_idx = dwc3_gadget_ep_get_transfer_index(dwc, - dep->number); - WARN_ON_ONCE(!dep->res_trans_idx); + 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; } @@ -994,28 +996,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->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 ret; + int start_trans = 1; + u8 trans_idx = dep->res_trans_idx; - start_trans = 1; if (usb_endpoint_xfer_isoc(dep->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; -- cgit v1.2.3-70-g09d2 From 3ef35fafdc87b72851f7785dc5331a0f4eb1b3ce Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 4 May 2012 12:58:14 +0300 Subject: usb: dwc3: define DWC3_EP0_BOUNCE_SIZE to avoid sprinkling magic constants on the driver we define a constant to be used when allocating setup_buffer and ep0_bounce buffer. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 1 + drivers/usb/dwc3/gadget.c | 13 +++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index ef28bd5680c..fbd0c8e30c1 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -51,6 +51,7 @@ #include /* Global constants */ +#define DWC3_EP0_BOUNCE_SIZE 512 #define DWC3_ENDPOINTS_NUM 32 #define DWC3_XHCI_RESOURCES_NUM 2 diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 31ffc5c2735..12844393bc3 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2319,7 +2319,7 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc) goto err1; } - dwc->setup_buf = kzalloc(512, 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; @@ -2327,7 +2327,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; @@ -2414,8 +2415,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); @@ -2444,8 +2445,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); -- cgit v1.2.3-70-g09d2 From 16e78db720baa9356485336ec137c7ee0a482a9b Mon Sep 17 00:00:00 2001 From: Ido Shayevitz Date: Mon, 12 Mar 2012 20:25:24 +0200 Subject: usb: dwc3: Update dwc3 udc to use usb_endpoint_descriptor inside the struct usb_ep Remove redundant pointer to struct usb_endpoint_descriptor. Signed-off-by: Ido Shayevitz Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 1 - drivers/usb/dwc3/ep0.c | 2 +- drivers/usb/dwc3/gadget.c | 37 ++++++++++++++++++------------------- 3 files changed, 19 insertions(+), 21 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 6c7945b4cad..9c5c73aae4f 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -361,7 +361,6 @@ struct dwc3_ep { dma_addr_t trb_pool_dma; u32 free_slot; u32 busy_slot; - const struct usb_endpoint_descriptor *desc; const struct usb_ss_ep_comp_descriptor *comp_desc; struct dwc3 *dwc; diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 3584a169886..3453ca1f747 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -179,7 +179,7 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, int ret; spin_lock_irqsave(&dwc->lock, flags); - if (!dep->desc) { + if (!dep->endpoint.desc) { dev_dbg(dwc->dev, "trying to queue request %p to disabled %s\n", request, dep->name); ret = -ESHUTDOWN; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 5255fe975ea..561625a1284 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -178,8 +178,8 @@ int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc) if (!(dep->flags & DWC3_EP_ENABLED)) continue; - if (usb_endpoint_xfer_bulk(dep->desc) - || usb_endpoint_xfer_isoc(dep->desc)) + if (usb_endpoint_xfer_bulk(dep->endpoint.desc) + || usb_endpoint_xfer_isoc(dep->endpoint.desc)) mult = 3; /* @@ -229,7 +229,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, * completed (not the LINK TRB). */ if (((dep->busy_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) && - usb_endpoint_xfer_isoc(dep->desc)) + usb_endpoint_xfer_isoc(dep->endpoint.desc)) dep->busy_slot++; } list_del(&req->list); @@ -470,7 +470,7 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, if (ret) return ret; - dep->desc = desc; + dep->endpoint.desc = desc; dep->comp_desc = comp_desc; dep->type = usb_endpoint_type(desc); dep->flags |= DWC3_EP_ENABLED; @@ -533,7 +533,6 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); dep->stream_capable = false; - dep->desc = NULL; dep->endpoint.desc = NULL; dep->comp_desc = NULL; dep->type = 0; @@ -694,7 +693,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, /* Skip the LINK-TRB on ISOC */ if (((cur_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) && - usb_endpoint_xfer_isoc(dep->desc)) + usb_endpoint_xfer_isoc(dep->endpoint.desc)) return; if (!req->trb) { @@ -707,7 +706,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, trb->bpl = lower_32_bits(dma); trb->bph = upper_32_bits(dma); - switch (usb_endpoint_type(dep->desc)) { + switch (usb_endpoint_type(dep->endpoint.desc)) { case USB_ENDPOINT_XFER_CONTROL: trb->ctrl = DWC3_TRBCTL_CONTROL_SETUP; break; @@ -732,7 +731,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, BUG(); } - if (usb_endpoint_xfer_isoc(dep->desc)) { + if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI; trb->ctrl |= DWC3_TRB_CTRL_CSP; } else { @@ -743,7 +742,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, trb->ctrl |= DWC3_TRB_CTRL_LST; } - if (usb_endpoint_xfer_bulk(dep->desc) && dep->stream_capable) + if (usb_endpoint_xfer_bulk(dep->endpoint.desc) && dep->stream_capable) trb->ctrl |= DWC3_TRB_CTRL_SID_SOFN(req->request.stream_id); trb->ctrl |= DWC3_TRB_CTRL_HWO; @@ -771,7 +770,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) trbs_left = (dep->busy_slot - dep->free_slot) & DWC3_TRB_MASK; /* Can't wrap around on a non-isoc EP since there's no link TRB */ - if (!usb_endpoint_xfer_isoc(dep->desc)) { + if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) { max = DWC3_TRB_NUM - (dep->free_slot & DWC3_TRB_MASK); if (trbs_left > max) trbs_left = max; @@ -797,7 +796,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) * processed from the first TRB until the last one. Since we * don't wrap around we have to start at the beginning. */ - if (usb_endpoint_xfer_isoc(dep->desc)) { + if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { dep->busy_slot = 1; dep->free_slot = 1; } else { @@ -807,7 +806,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) } /* The last TRB is a link TRB, not used for xfer */ - if ((trbs_left <= 1) && usb_endpoint_xfer_isoc(dep->desc)) + if ((trbs_left <= 1) && usb_endpoint_xfer_isoc(dep->endpoint.desc)) return; list_for_each_entry_safe(req, n, &dep->request_list, list) { @@ -984,7 +983,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) int start_trans; start_trans = 1; - if (usb_endpoint_xfer_isoc(dep->desc) && + if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && (dep->flags & DWC3_EP_BUSY)) start_trans = 0; @@ -1011,7 +1010,7 @@ static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request, int ret; - if (!dep->desc) { + if (!dep->endpoint.desc) { dev_dbg(dwc->dev, "trying to queue request %p to disabled %s\n", request, ep->name); return -ESHUTDOWN; @@ -1125,7 +1124,7 @@ static int dwc3_gadget_ep_set_halt(struct usb_ep *ep, int value) spin_lock_irqsave(&dwc->lock, flags); - if (usb_endpoint_xfer_isoc(dep->desc)) { + if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { dev_err(dwc->dev, "%s is of Isochronous type\n", dep->name); ret = -EINVAL; goto out; @@ -1681,7 +1680,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, case DWC3_DEPEVT_XFERCOMPLETE: dep->res_trans_idx = 0; - if (usb_endpoint_xfer_isoc(dep->desc)) { + if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { dev_dbg(dwc->dev, "%s is an Isochronous endpoint\n", dep->name); return; @@ -1690,7 +1689,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, dwc3_endpoint_transfer_complete(dwc, dep, event, 1); break; case DWC3_DEPEVT_XFERINPROGRESS: - if (!usb_endpoint_xfer_isoc(dep->desc)) { + if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) { dev_dbg(dwc->dev, "%s is not an Isochronous endpoint\n", dep->name); return; @@ -1699,7 +1698,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, dwc3_endpoint_transfer_complete(dwc, dep, event, 0); break; case DWC3_DEPEVT_XFERNOTREADY: - if (usb_endpoint_xfer_isoc(dep->desc)) { + if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { dwc3_gadget_start_isoc(dwc, dep, event); } else { int ret; @@ -1720,7 +1719,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, break; case DWC3_DEPEVT_STREAMEVT: - if (!usb_endpoint_xfer_bulk(dep->desc)) { + if (!usb_endpoint_xfer_bulk(dep->endpoint.desc)) { dev_err(dwc->dev, "Stream event for non-Bulk %s\n", dep->name); return; -- cgit v1.2.3-70-g09d2 From b8cacf33f09c60208a914b36b3e6de8e9ba228d5 Mon Sep 17 00:00:00 2001 From: joseph daniel Date: Fri, 11 May 2012 15:53:40 +0530 Subject: usb: dwc3: Fix the dwc3 dependency The warning shown up when ran with randconfig, warning: (USB_DWC3) selects USB_XHCI_PLATFORM which has unmet direct dependencies (USB_SUPPORT && USB_XHCI_HCD) Signed-off-by: joseph daniel Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index d8f741f9e56..d13c60f4213 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -4,7 +4,7 @@ config USB_DWC3 select USB_OTG_UTILS select USB_GADGET_DUALSPEED select USB_GADGET_SUPERSPEED - select USB_XHCI_PLATFORM + select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD help Say Y or M here if your system has a Dual Role SuperSpeed USB controller based on the DesignWare USB3 IP Core. -- cgit v1.2.3-70-g09d2 From e8d4e8be860d935099ffcf695dcd29b55ae50b36 Mon Sep 17 00:00:00 2001 From: Pratyush Anand Date: Fri, 15 Jun 2012 11:54:00 +0530 Subject: usb: dwc3: fix giveback of queued request in ep_dequeue In case of ep_dequeue , if dequeued request was submitted for dma transfer, then endpoint is stopped. Once endpoint is stooped, callback for the dequeued request must be called. Signed-off-by: Pratyush Anand Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 3df1a1973b0..ec70df7aba1 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1091,7 +1091,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, if (r == req) { /* wait until it is processed */ dwc3_stop_active_transfer(dwc, dep->number); - goto out0; + goto out1; } dev_err(dwc->dev, "request %p was not queued to %s\n", request, ep->name); @@ -1099,6 +1099,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, goto out0; } +out1: /* giveback the request */ dwc3_gadget_giveback(dep, req, -ECONNRESET); -- cgit v1.2.3-70-g09d2