]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.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)
committerFelipe Balbi <balbi@ti.com>
Fri, 9 Oct 2015 21:06:58 +0000 (16:06 -0500)
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.

Cc: <stable@vger.kernel.org> # v3.18+
Signed-off-by: John Youn <johnyoun@synopsys.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
drivers/usb/dwc3/core.c
drivers/usb/dwc3/core.h

index c72c8c5c1c5a858470dda715aa07be1794fc6795..1e276d5662f25683c4a7c141404c0f4781c2c308 100644 (file)
@@ -534,12 +534,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 91887455133addb04970ab7d4e067db5695df58e..0d65be7445527826c8de34b93d6b15b5a954d6cc 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))
 
@@ -771,6 +774,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
@@ -793,6 +804,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;