]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
usb: dwc3: Support Synopsys USB 3.1 IP
authorJohn Youn <John.Youn@synopsys.com>
Sat, 5 Sep 2015 02:15:10 +0000 (19:15 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 9 Dec 2015 19:34:36 +0000 (14:34 -0500)
commit 690fb3718a70c66004342f6f5e2e8a5f95b977db upstream.

This patch allows the dwc3 driver to run on the new Synopsys USB 3.1
IP core, albeit in USB 3.0 mode only.

The Synopsys USB 3.1 IP (DWC_usb31) retains mostly the same register
interface and programming model as the existing USB 3.0 controller IP
(DWC_usb3). However the GSNPSID and version numbers are different.

Add checking for the new ID to pass driver probe.

Also, since the DWC_usb31 version number is lower in value than the
full GSNPSID of the DWC_usb3 IP, we set the high bit to identify
DWC_usb31 and to ensure the values are higher.

Finally, add a documentation note about the revision numbering scheme.
Any future revision checks (for STARS, workarounds, and new features)
should take into consideration how it applies to both the 3.1/3.0 IP.

Signed-off-by: John Youn <johnyoun@synopsys.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/dwc3/core.c
drivers/usb/dwc3/core.h

index 064123e445664a5e23bb28ba48cfb1755ec7fb88..386ea764d8b2c23418785a569006491dde3756ae 100644 (file)
@@ -507,12 +507,18 @@ static int dwc3_core_init(struct dwc3 *dwc)
 
        reg = dwc3_readl(dwc->regs, DWC3_GSNPSID);
        /* This should read as U3 followed by revision number */
-       if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) {
+       if ((reg & DWC3_GSNPSID_MASK) == 0x55330000) {
+               /* Detected DWC_usb3 IP */
+               dwc->revision = reg;
+       } else if ((reg & DWC3_GSNPSID_MASK) == 0x33310000) {
+               /* Detected DWC_usb31 IP */
+               dwc->revision = dwc3_readl(dwc->regs, DWC3_VER_NUMBER);
+               dwc->revision |= DWC3_REVISION_IS_DWC31;
+       } else {
                dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n");
                ret = -ENODEV;
                goto err0;
        }
-       dwc->revision = reg;
 
        /*
         * Write Linux Version Code to our GUID register so it's easy to figure
index 0447788845856e57190561b1117253200c1050a6..1841dd025ea7a5e24535dcff823a9b8c89f7857c 100644 (file)
 #define DWC3_GPRTBIMAP_FS0     0xc188
 #define DWC3_GPRTBIMAP_FS1     0xc18c
 
+#define DWC3_VER_NUMBER                0xc1a0
+#define DWC3_VER_TYPE          0xc1a4
+
 #define DWC3_GUSB2PHYCFG(n)    (0xc200 + (n * 0x04))
 #define DWC3_GUSB2I2CCTL(n)    (0xc240 + (n * 0x04))
 
@@ -766,6 +769,14 @@ struct dwc3 {
        u32                     num_event_buffers;
        u32                     u1u2;
        u32                     maximum_speed;
+
+       /*
+        * All 3.1 IP version constants are greater than the 3.0 IP
+        * version constants. This works for most version checks in
+        * dwc3. However, in the future, this may not apply as
+        * features may be developed on newer versions of the 3.0 IP
+        * that are not in the 3.1 IP.
+        */
        u32                     revision;
 
 #define DWC3_REVISION_173A     0x5533173a
@@ -788,6 +799,13 @@ struct dwc3 {
 #define DWC3_REVISION_270A     0x5533270a
 #define DWC3_REVISION_280A     0x5533280a
 
+/*
+ * NOTICE: we're using bit 31 as a "is usb 3.1" flag. This is really
+ * just so dwc31 revisions are always larger than dwc3.
+ */
+#define DWC3_REVISION_IS_DWC31         0x80000000
+#define DWC3_USB31_REVISION_110A       (0x3131302a | DWC3_REVISION_IS_USB31)
+
        enum dwc3_ep0_next      ep0_next_event;
        enum dwc3_ep0_state     ep0state;
        enum dwc3_link_state    link_state;