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

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
...@@ -410,7 +410,6 @@ static int __devinit dwc3_probe(struct platform_device *pdev) ...@@ -410,7 +410,6 @@ static int __devinit dwc3_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
int ret = -ENOMEM; int ret = -ENOMEM;
int irq;
void __iomem *regs; void __iomem *regs;
void *mem; void *mem;
...@@ -425,15 +424,28 @@ static int __devinit dwc3_probe(struct platform_device *pdev) ...@@ -425,15 +424,28 @@ static int __devinit dwc3_probe(struct platform_device *pdev)
dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1); dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1);
dwc->mem = mem; dwc->mem = mem;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res) { if (!res) {
dev_err(dev, "missing resource\n"); dev_err(dev, "missing IRQ\n");
return -ENODEV; return -ENODEV;
} }
dwc->xhci_resources[1] = *res;
dwc->res = res; res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
res = devm_request_mem_region(dev, res->start, resource_size(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)); dev_name(dev));
if (!res) { if (!res) {
dev_err(dev, "can't request mem region\n"); dev_err(dev, "can't request mem region\n");
...@@ -446,19 +458,12 @@ static int __devinit dwc3_probe(struct platform_device *pdev) ...@@ -446,19 +458,12 @@ static int __devinit dwc3_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
} }
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "missing IRQ\n");
return -ENODEV;
}
spin_lock_init(&dwc->lock); spin_lock_init(&dwc->lock);
platform_set_drvdata(pdev, dwc); platform_set_drvdata(pdev, dwc);
dwc->regs = regs; dwc->regs = regs;
dwc->regs_size = resource_size(res); dwc->regs_size = resource_size(res);
dwc->dev = dev; dwc->dev = dev;
dwc->irq = irq;
if (!strncmp("super", maximum_speed, 5)) if (!strncmp("super", maximum_speed, 5))
dwc->maximum_speed = DWC3_DCFG_SUPERSPEED; dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
......
...@@ -51,7 +51,9 @@ ...@@ -51,7 +51,9 @@
#include <linux/usb/gadget.h> #include <linux/usb/gadget.h>
/* Global constants */ /* Global constants */
#define DWC3_EP0_BOUNCE_SIZE 512
#define DWC3_ENDPOINTS_NUM 32 #define DWC3_ENDPOINTS_NUM 32
#define DWC3_XHCI_RESOURCES_NUM 2
#define DWC3_EVENT_BUFFERS_SIZE PAGE_SIZE #define DWC3_EVENT_BUFFERS_SIZE PAGE_SIZE
#define DWC3_EVENT_TYPE_MASK 0xfe #define DWC3_EVENT_TYPE_MASK 0xfe
...@@ -75,6 +77,16 @@ ...@@ -75,6 +77,16 @@
#define DWC3_GSNPSID_MASK 0xffff0000 #define DWC3_GSNPSID_MASK 0xffff0000
#define DWC3_GSNPSREV_MASK 0xffff #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 */ /* Global Registers */
#define DWC3_GSBUSCFG0 0xc100 #define DWC3_GSBUSCFG0 0xc100
#define DWC3_GSBUSCFG1 0xc104 #define DWC3_GSBUSCFG1 0xc104
...@@ -183,6 +195,7 @@ ...@@ -183,6 +195,7 @@
#define DWC3_GHWPARAMS1_EN_PWROPT_CLK 1 #define DWC3_GHWPARAMS1_EN_PWROPT_CLK 1
/* Device Configuration Register */ /* Device Configuration Register */
#define DWC3_DCFG_LPM_CAP (1 << 22)
#define DWC3_DCFG_DEVADDR(addr) ((addr) << 3) #define DWC3_DCFG_DEVADDR(addr) ((addr) << 3)
#define DWC3_DCFG_DEVADDR_MASK DWC3_DCFG_DEVADDR(0x7f) #define DWC3_DCFG_DEVADDR_MASK DWC3_DCFG_DEVADDR(0x7f)
...@@ -272,12 +285,14 @@ ...@@ -272,12 +285,14 @@
#define DWC3_DGCMD_SET_ENDPOINT_NRDY 0x0c #define DWC3_DGCMD_SET_ENDPOINT_NRDY 0x0c
#define DWC3_DGCMD_RUN_SOC_BUS_LOOPBACK 0x10 #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 */ /* Device Endpoint Command Register */
#define DWC3_DEPCMD_PARAM_SHIFT 16 #define DWC3_DEPCMD_PARAM_SHIFT 16
#define DWC3_DEPCMD_PARAM(x) ((x) << DWC3_DEPCMD_PARAM_SHIFT) #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_GET_RSC_IDX(x) (((x) >> DWC3_DEPCMD_PARAM_SHIFT) & 0x7f)
#define DWC3_DEPCMD_STATUS_MASK (0x0f << 12) #define DWC3_DEPCMD_STATUS(x) (((x) >> 15) & 1)
#define DWC3_DEPCMD_STATUS(x) (((x) & DWC3_DEPCMD_STATUS_MASK) >> 12)
#define DWC3_DEPCMD_HIPRI_FORCERM (1 << 11) #define DWC3_DEPCMD_HIPRI_FORCERM (1 << 11)
#define DWC3_DEPCMD_CMDACT (1 << 10) #define DWC3_DEPCMD_CMDACT (1 << 10)
#define DWC3_DEPCMD_CMDIOC (1 << 8) #define DWC3_DEPCMD_CMDIOC (1 << 8)
...@@ -560,6 +575,11 @@ struct dwc3_request { ...@@ -560,6 +575,11 @@ struct dwc3_request {
* @setup_packet_pending: true when there's a Setup Packet in FIFO. Workaround * @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 * @needs_fifo_resize: not all users might want fifo resizing, flag it
* @resize_fifos: tells us it's ok to reconfigure our TxFIFO sizes. * @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 * @ep0_next_event: hold the next expected event
* @ep0state: state of endpoint zero * @ep0state: state of endpoint zero
* @link_state: link state * @link_state: link state
...@@ -582,7 +602,7 @@ struct dwc3 { ...@@ -582,7 +602,7 @@ struct dwc3 {
struct device *dev; struct device *dev;
struct platform_device *xhci; struct platform_device *xhci;
struct resource *res; struct resource xhci_resources[DWC3_XHCI_RESOURCES_NUM];
struct dwc3_event_buffer **ev_buffs; struct dwc3_event_buffer **ev_buffs;
struct dwc3_ep *eps[DWC3_ENDPOINTS_NUM]; struct dwc3_ep *eps[DWC3_ENDPOINTS_NUM];
...@@ -593,8 +613,6 @@ struct dwc3 { ...@@ -593,8 +613,6 @@ struct dwc3 {
void __iomem *regs; void __iomem *regs;
size_t regs_size; size_t regs_size;
int irq;
u32 num_event_buffers; u32 num_event_buffers;
u32 u1u2; u32 u1u2;
u32 maximum_speed; u32 maximum_speed;
...@@ -608,6 +626,10 @@ struct dwc3 { ...@@ -608,6 +626,10 @@ struct dwc3 {
#define DWC3_REVISION_185A 0x5533185a #define DWC3_REVISION_185A 0x5533185a
#define DWC3_REVISION_188A 0x5533188a #define DWC3_REVISION_188A 0x5533188a
#define DWC3_REVISION_190A 0x5533190a #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 is_selfpowered:1;
unsigned three_stage_setup:1; unsigned three_stage_setup:1;
...@@ -624,7 +646,14 @@ struct dwc3 { ...@@ -624,7 +646,14 @@ struct dwc3 {
enum dwc3_link_state link_state; enum dwc3_link_state link_state;
enum dwc3_device_state dev_state; enum dwc3_device_state dev_state;
u16 isoch_delay;
u16 u2sel;
u16 u2pel;
u8 u1sel;
u8 u1pel;
u8 speed; u8 speed;
void *mem; void *mem;
struct dwc3_hwparams hwparams; struct dwc3_hwparams hwparams;
......
...@@ -49,7 +49,6 @@ ...@@ -49,7 +49,6 @@
#include <linux/of.h> #include <linux/of.h>
#include "core.h" #include "core.h"
#include "io.h"
/* /*
* All these registers belong to OMAP's Wrapper around the * All these registers belong to OMAP's Wrapper around the
...@@ -143,6 +142,17 @@ struct dwc3_omap { ...@@ -143,6 +142,17 @@ struct dwc3_omap {
u32 dma_status:1; 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) static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
{ {
struct dwc3_omap *omap = _omap; struct dwc3_omap *omap = _omap;
...@@ -150,7 +160,7 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap) ...@@ -150,7 +160,7 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
spin_lock(&omap->lock); 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) { if (reg & USBOTGSS_IRQ1_DMADISABLECLR) {
dev_dbg(omap->dev, "DMA Disable was Cleared\n"); dev_dbg(omap->dev, "DMA Disable was Cleared\n");
...@@ -184,10 +194,10 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap) ...@@ -184,10 +194,10 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
if (reg & USBOTGSS_IRQ1_IDPULLUP_FALL) if (reg & USBOTGSS_IRQ1_IDPULLUP_FALL)
dev_dbg(omap->dev, "IDPULLUP Fall\n"); 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); reg = dwc3_omap_readl(omap->base, USBOTGSS_IRQSTATUS_0);
dwc3_writel(omap->base, USBOTGSS_IRQSTATUS_0, reg); dwc3_omap_writel(omap->base, USBOTGSS_IRQSTATUS_0, reg);
spin_unlock(&omap->lock); spin_unlock(&omap->lock);
...@@ -270,7 +280,7 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev) ...@@ -270,7 +280,7 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
omap->base = base; omap->base = base;
omap->dwc3 = dwc3; 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); utmi_mode = of_get_property(node, "utmi-mode", &size);
if (utmi_mode && size == sizeof(*utmi_mode)) { if (utmi_mode && size == sizeof(*utmi_mode)) {
...@@ -293,10 +303,10 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev) ...@@ -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 */ /* 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); omap->dma_status = !!(reg & USBOTGSS_SYSCONFIG_DMADISABLE);
/* Set No-Idle and No-Standby */ /* Set No-Idle and No-Standby */
...@@ -306,7 +316,7 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev) ...@@ -306,7 +316,7 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
reg |= (USBOTGSS_SYSCONFIG_STANDBYMODE(USBOTGSS_STANDBYMODE_NO_STANDBY) reg |= (USBOTGSS_SYSCONFIG_STANDBYMODE(USBOTGSS_STANDBYMODE_NO_STANDBY)
| USBOTGSS_SYSCONFIG_IDLEMODE(USBOTGSS_IDLEMODE_NO_IDLE)); | 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, ret = devm_request_irq(dev, omap->irq, dwc3_omap_interrupt, 0,
"dwc3-omap", omap); "dwc3-omap", omap);
...@@ -318,7 +328,7 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev) ...@@ -318,7 +328,7 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
/* enable all IRQs */ /* enable all IRQs */
reg = USBOTGSS_IRQO_COREIRQ_ST; 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 | reg = (USBOTGSS_IRQ1_OEVT |
USBOTGSS_IRQ1_DRVVBUS_RISE | USBOTGSS_IRQ1_DRVVBUS_RISE |
...@@ -330,7 +340,7 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev) ...@@ -330,7 +340,7 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
USBOTGSS_IRQ1_DISCHRGVBUS_FALL | USBOTGSS_IRQ1_DISCHRGVBUS_FALL |
USBOTGSS_IRQ1_IDPULLUP_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, ret = platform_device_add_resources(dwc3, pdev->resource,
pdev->num_resources); pdev->num_resources);
......
...@@ -261,6 +261,7 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc, ...@@ -261,6 +261,7 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc,
{ {
struct dwc3_ep *dep; struct dwc3_ep *dep;
u32 recip; u32 recip;
u32 reg;
u16 usb_status = 0; u16 usb_status = 0;
__le16 *response_pkt; __le16 *response_pkt;
...@@ -268,10 +269,18 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc, ...@@ -268,10 +269,18 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc,
switch (recip) { switch (recip) {
case USB_RECIP_DEVICE: case USB_RECIP_DEVICE:
/* /*
* We are self-powered. U1/U2/LTM will be set later * LTM will be set once we know how to set this in HW.
* once we handle this states. RemoteWakeup is 0 on SS
*/ */
usb_status |= dwc->is_selfpowered << USB_DEVICE_SELF_POWERED; 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; break;
case USB_RECIP_INTERFACE: case USB_RECIP_INTERFACE:
...@@ -312,6 +321,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc, ...@@ -312,6 +321,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
u32 recip; u32 recip;
u32 wValue; u32 wValue;
u32 wIndex; u32 wIndex;
u32 reg;
int ret; int ret;
wValue = le16_to_cpu(ctrl->wValue); wValue = le16_to_cpu(ctrl->wValue);
...@@ -320,29 +330,43 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc, ...@@ -320,29 +330,43 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
switch (recip) { switch (recip) {
case USB_RECIP_DEVICE: case USB_RECIP_DEVICE:
switch (wValue) {
case USB_DEVICE_REMOTE_WAKEUP:
break;
/* /*
* 9.4.1 says only only for SS, in AddressState only for * 9.4.1 says only only for SS, in AddressState only for
* default control pipe * default control pipe
*/ */
switch (wValue) {
case USB_DEVICE_U1_ENABLE: case USB_DEVICE_U1_ENABLE:
case USB_DEVICE_U2_ENABLE:
case USB_DEVICE_LTM_ENABLE:
if (dwc->dev_state != DWC3_CONFIGURED_STATE) if (dwc->dev_state != DWC3_CONFIGURED_STATE)
return -EINVAL; return -EINVAL;
if (dwc->speed != DWC3_DSTS_SUPERSPEED) if (dwc->speed != DWC3_DSTS_SUPERSPEED)
return -EINVAL; return -EINVAL;
}
/* XXX add U[12] & LTM */ reg = dwc3_readl(dwc->regs, DWC3_DCTL);
switch (wValue) { if (set)
case USB_DEVICE_REMOTE_WAKEUP: reg |= DWC3_DCTL_INITU1ENA;
break; else
case USB_DEVICE_U1_ENABLE: reg &= ~DWC3_DCTL_INITU1ENA;
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
break; break;
case USB_DEVICE_U2_ENABLE: 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; break;
case USB_DEVICE_LTM_ENABLE: case USB_DEVICE_LTM_ENABLE:
return -EINVAL;
break; break;
case USB_DEVICE_TEST_MODE: case USB_DEVICE_TEST_MODE:
...@@ -469,6 +493,107 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) ...@@ -469,6 +493,107 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
return ret; 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) static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
{ {
int ret; int ret;
...@@ -494,6 +619,14 @@ static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) ...@@ -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"); dev_vdbg(dwc->dev, "USB_REQ_SET_CONFIGURATION\n");
ret = dwc3_ep0_set_config(dwc, ctrl); ret = dwc3_ep0_set_config(dwc, ctrl);
break; 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: default:
dev_vdbg(dwc->dev, "Forwarding to gadget driver\n"); dev_vdbg(dwc->dev, "Forwarding to gadget driver\n");
ret = dwc3_ep0_delegate_req(dwc, ctrl); ret = dwc3_ep0_delegate_req(dwc, ctrl);
......
...@@ -276,6 +276,33 @@ static const char *dwc3_gadget_ep_cmd_string(u8 cmd) ...@@ -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, int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep,
unsigned cmd, struct dwc3_gadget_ep_cmd_params *params) 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, ...@@ -929,10 +956,12 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param,
} }
dep->flags |= DWC3_EP_BUSY; 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; return 0;
} }
...@@ -966,28 +995,37 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) ...@@ -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); 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 * There are two special cases:
* empty list of requests. We need to kick the *
* transfer here in that situation, otherwise * 1. XferNotReady with empty list of requests. We need to kick the
* we will be NAKing forever. * 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.
* *
* If we get XferNotReady before gadget driver * 2. XferInProgress on Isoc EP with an active transfer. We need to
* has a chance to queue a request, we will ACK * kick the transfer here after queuing a request, otherwise the
* the IRQ but won't be able to receive the data * core may not see the modified TRB(s).
* until the next request is queued. The following
* code is handling exactly that.
*/ */
if (dep->flags & DWC3_EP_PENDING_REQUEST) { if (dep->flags & DWC3_EP_PENDING_REQUEST) {
int ret; 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) && if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
(dep->flags & DWC3_EP_BUSY)) (dep->flags & DWC3_EP_BUSY)) {
start_trans = 0; 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) { if (ret && ret != -EBUSY) {
struct dwc3 *dwc = dep->dwc; struct dwc3 *dwc = dep->dwc;
...@@ -1355,7 +1393,24 @@ static int dwc3_gadget_start(struct usb_gadget *g, ...@@ -1355,7 +1393,24 @@ static int dwc3_gadget_start(struct usb_gadget *g,
reg = dwc3_readl(dwc->regs, DWC3_DCFG); reg = dwc3_readl(dwc->regs, DWC3_DCFG);
reg &= ~(DWC3_DCFG_SPEED_MASK); 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); dwc3_writel(dwc->regs, DWC3_DCFG, reg);
dwc->start_config_issued = false; dwc->start_config_issued = false;
...@@ -1915,6 +1970,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) ...@@ -1915,6 +1970,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
reg = dwc3_readl(dwc->regs, DWC3_DCTL); reg = dwc3_readl(dwc->regs, DWC3_DCTL);
reg &= ~DWC3_DCTL_TSTCTRL_MASK; reg &= ~DWC3_DCTL_TSTCTRL_MASK;
reg &= ~(DWC3_DCTL_INITU1ENA | DWC3_DCTL_INITU2ENA);
dwc3_writel(dwc->regs, DWC3_DCTL, reg); dwc3_writel(dwc->regs, DWC3_DCTL, reg);
dwc->test_mode = false; dwc->test_mode = false;
...@@ -2262,8 +2318,7 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc) ...@@ -2262,8 +2318,7 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc)
goto err1; goto err1;
} }
dwc->setup_buf = kzalloc(sizeof(*dwc->setup_buf) * 2, dwc->setup_buf = kzalloc(DWC3_EP0_BOUNCE_SIZE, GFP_KERNEL);
GFP_KERNEL);
if (!dwc->setup_buf) { if (!dwc->setup_buf) {
dev_err(dwc->dev, "failed to allocate setup buffer\n"); dev_err(dwc->dev, "failed to allocate setup buffer\n");
ret = -ENOMEM; ret = -ENOMEM;
...@@ -2271,7 +2326,8 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc) ...@@ -2271,7 +2326,8 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc)
} }
dwc->ep0_bounce = dma_alloc_coherent(dwc->dev, 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) { if (!dwc->ep0_bounce) {
dev_err(dwc->dev, "failed to allocate ep0 bounce buffer\n"); dev_err(dwc->dev, "failed to allocate ep0 bounce buffer\n");
ret = -ENOMEM; ret = -ENOMEM;
...@@ -2312,6 +2368,14 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc) ...@@ -2312,6 +2368,14 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc)
goto err5; 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 */ /* Enable all but Start and End of Frame IRQs */
reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN | reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN |
DWC3_DEVTEN_EVNTOVERFLOWEN | DWC3_DEVTEN_EVNTOVERFLOWEN |
...@@ -2350,8 +2414,8 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc) ...@@ -2350,8 +2414,8 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc)
dwc3_gadget_free_endpoints(dwc); dwc3_gadget_free_endpoints(dwc);
err4: err4:
dma_free_coherent(dwc->dev, 512, dwc->ep0_bounce, dma_free_coherent(dwc->dev, DWC3_EP0_BOUNCE_SIZE,
dwc->ep0_bounce_addr); dwc->ep0_bounce, dwc->ep0_bounce_addr);
err3: err3:
kfree(dwc->setup_buf); kfree(dwc->setup_buf);
...@@ -2380,8 +2444,8 @@ void dwc3_gadget_exit(struct dwc3 *dwc) ...@@ -2380,8 +2444,8 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
dwc3_gadget_free_endpoints(dwc); dwc3_gadget_free_endpoints(dwc);
dma_free_coherent(dwc->dev, 512, dwc->ep0_bounce, dma_free_coherent(dwc->dev, DWC3_EP0_BOUNCE_SIZE,
dwc->ep0_bounce_addr); dwc->ep0_bounce, dwc->ep0_bounce_addr);
kfree(dwc->setup_buf); kfree(dwc->setup_buf);
......
...@@ -111,6 +111,7 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, ...@@ -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_gadget_ep_set_halt(struct dwc3_ep *dep, int value);
int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep, int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep,
unsigned cmd, struct dwc3_gadget_ep_cmd_params *params); 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 * dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW
......
...@@ -39,15 +39,6 @@ ...@@ -39,15 +39,6 @@
#include "core.h" #include "core.h"
static struct resource generic_resources[] = {
{
.flags = IORESOURCE_IRQ,
},
{
.flags = IORESOURCE_MEM,
},
};
int dwc3_host_init(struct dwc3 *dwc) int dwc3_host_init(struct dwc3 *dwc)
{ {
struct platform_device *xhci; struct platform_device *xhci;
...@@ -68,14 +59,8 @@ int dwc3_host_init(struct dwc3 *dwc) ...@@ -68,14 +59,8 @@ int dwc3_host_init(struct dwc3 *dwc)
dwc->xhci = xhci; dwc->xhci = xhci;
/* setup resources */ ret = platform_device_add_resources(xhci, dwc->xhci_resources,
generic_resources[0].start = dwc->irq; DWC3_XHCI_RESOURCES_NUM);
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));
if (ret) { if (ret) {
dev_err(dwc->dev, "couldn't add resources to xHCI device\n"); dev_err(dwc->dev, "couldn't add resources to xHCI device\n");
goto err1; goto err1;
......
...@@ -41,14 +41,26 @@ ...@@ -41,14 +41,26 @@
#include <linux/io.h> #include <linux/io.h>
#include "core.h"
static inline u32 dwc3_readl(void __iomem *base, u32 offset) 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) 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 */ #endif /* __DRIVERS_USB_DWC3_IO_H */
...@@ -88,6 +88,8 @@ ...@@ -88,6 +88,8 @@
#define USB_REQ_GET_INTERFACE 0x0A #define USB_REQ_GET_INTERFACE 0x0A
#define USB_REQ_SET_INTERFACE 0x0B #define USB_REQ_SET_INTERFACE 0x0B
#define USB_REQ_SYNCH_FRAME 0x0C #define USB_REQ_SYNCH_FRAME 0x0C
#define USB_REQ_SET_SEL 0x30
#define USB_REQ_SET_ISOCH_DELAY 0x31
#define USB_REQ_SET_ENCRYPTION 0x0D /* Wireless USB */ #define USB_REQ_SET_ENCRYPTION 0x0D /* Wireless USB */
#define USB_REQ_GET_ENCRYPTION 0x0E #define USB_REQ_GET_ENCRYPTION 0x0E
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment