From: Chris Morgan <[email protected]>

Add support for the ip and version_type fields from the Linux
version of the dwc3 driver. Included in this is support for a
few additional macros in the header from Linux as well.

Signed-off-by: Chris Morgan <[email protected]>
---
 drivers/usb/dwc3/core.c | 26 ++++++++++++++----
 drivers/usb/dwc3/core.h | 60 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 81 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 847fa1f82c3..4827c83e96d 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -580,6 +580,26 @@ static void dwc3_set_incr_burst_type(struct dwc3 *dwc)
        dwc3_writel(dwc->regs, DWC3_GSBUSCFG0, cfg);
 }
 
+static bool dwc3_core_is_valid(struct dwc3 *dwc)
+{
+       u32 reg;
+
+       reg = dwc3_readl(dwc->regs, DWC3_GSNPSID);
+       dwc->ip = DWC3_GSNPS_ID(reg);
+
+       /* This should read as U3 followed by revision number */
+       if (DWC3_IP_IS(DWC3)) {
+               dwc->revision = reg;
+       } else if (DWC3_IP_IS(DWC31) || DWC3_IP_IS(DWC32)) {
+               dwc->revision = dwc3_readl(dwc->regs, DWC3_VER_NUMBER);
+               dwc->version_type = dwc3_readl(dwc->regs, DWC3_VER_TYPE);
+       } else {
+               return false;
+       }
+
+       return true;
+}
+
 /**
  * dwc3_core_init - Low-level initialization of DWC3 Core
  * @dwc: Pointer to our controller context structure
@@ -592,15 +612,11 @@ static int dwc3_core_init(struct dwc3 *dwc)
        u32                     reg;
        int                     ret;
 
-       reg = dwc3_readl(dwc->regs, DWC3_GSNPSID);
-       /* This should read as U3 followed by revision number */
-       if ((reg & DWC3_GSNPSID_MASK) != 0x55330000 &&
-           (reg & DWC3_GSNPSID_MASK) != 0x33310000) {
+       if (!dwc3_core_is_valid(dwc)) {
                dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n");
                ret = -ENODEV;
                goto err0;
        }
-       dwc->revision = reg;
 
        /* Handle USB2.0-only core configuration */
        if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) ==
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index b572ea340c8..cdbfdce76bb 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -56,6 +56,7 @@
 #define DWC3_GEVNTCOUNT_MASK   0xfffc
 #define DWC3_GSNPSID_MASK      0xffff0000
 #define DWC3_GSNPSREV_MASK     0xffff
+#define DWC3_GSNPS_ID(p)       (((p) & DWC3_GSNPSID_MASK) >> 16)
 
 /* DWC3 registers memory space boundries */
 #define DWC3_XHCI_REGS_START           0x0
@@ -99,6 +100,9 @@
 #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))
 
@@ -686,7 +690,9 @@ struct dwc3_scratchpad_array {
  * @num_event_buffers: calculated number of event buffers
  * @u1u2: only used on revisions <1.83a for workaround
  * @maximum_speed: maximum speed requested (mainly for testing purposes)
+ * @ip: controller's ID
  * @revision: revision register contents
+ * @version_type: VERSIONTYPE register contents, a sub release of a revision
  * @dr_mode: requested mode of operation
  * @hsphy_mode: UTMI phy mode, one of following:
  *             - USBPHY_INTERFACE_MODE_UTMI
@@ -795,6 +801,13 @@ struct dwc3 {
        u32                     num_event_buffers;
        u32                     u1u2;
        u32                     maximum_speed;
+
+       u32                     ip;
+
+#define DWC3_IP                        0x5533
+#define DWC31_IP               0x3331
+#define DWC32_IP               0x3332
+
        u32                     revision;
 
 #define DWC3_REVISION_173A     0x5533173a
@@ -817,6 +830,32 @@ struct dwc3 {
 #define DWC3_REVISION_270A     0x5533270a
 #define DWC3_REVISION_280A     0x5533280a
 #define DWC3_REVISION_290A     0x5533290a
+#define DWC3_REVISION_300A     0x5533300a
+#define DWC3_REVISION_310A     0x5533310a
+#define DWC3_REVISION_320A     0x5533320a
+#define DWC3_REVISION_330A     0x5533330a
+
+#define DWC31_REVISION_ANY     0x0
+#define DWC31_REVISION_110A    0x3131302a
+#define DWC31_REVISION_120A    0x3132302a
+#define DWC31_REVISION_160A    0x3136302a
+#define DWC31_REVISION_170A    0x3137302a
+#define DWC31_REVISION_180A    0x3138302a
+#define DWC31_REVISION_190A    0x3139302a
+#define DWC31_REVISION_200A    0x3230302a
+
+#define DWC32_REVISION_ANY     0x0
+#define DWC32_REVISION_100A    0x3130302a
+
+       u32                     version_type;
+
+#define DWC31_VERSIONTYPE_ANY          0x0
+#define DWC31_VERSIONTYPE_EA01         0x65613031
+#define DWC31_VERSIONTYPE_EA02         0x65613032
+#define DWC31_VERSIONTYPE_EA03         0x65613033
+#define DWC31_VERSIONTYPE_EA04         0x65613034
+#define DWC31_VERSIONTYPE_EA05         0x65613035
+#define DWC31_VERSIONTYPE_EA06         0x65613036
 
        enum dwc3_ep0_next      ep0_next_event;
        enum dwc3_ep0_state     ep0state;
@@ -1062,6 +1101,27 @@ void dwc3_of_parse(struct dwc3 *dwc);
 int dwc3_init(struct dwc3 *dwc);
 void dwc3_remove(struct dwc3 *dwc);
 
+#define DWC3_IP_IS(_ip)                                                        
\
+       (dwc->ip == _ip##_IP)
+
+#define DWC3_VER_IS(_ip, _ver)                                         \
+       (DWC3_IP_IS(_ip) && dwc->revision == _ip##_REVISION_##_ver)
+
+#define DWC3_VER_IS_PRIOR(_ip, _ver)                                   \
+       (DWC3_IP_IS(_ip) && dwc->revision < _ip##_REVISION_##_ver)
+
+#define DWC3_VER_IS_WITHIN(_ip, _from, _to)                            \
+       (DWC3_IP_IS(_ip) &&                                             \
+        dwc->revision >= _ip##_REVISION_##_from &&                     \
+        (!(_ip##_REVISION_##_to) ||                                    \
+         dwc->revision <= _ip##_REVISION_##_to))
+
+#define DWC3_VER_TYPE_IS_WITHIN(_ip, _ver, _from, _to)                 \
+       (DWC3_VER_IS(_ip, _ver) &&                                      \
+        dwc->version_type >= _ip##_VERSIONTYPE_##_from &&              \
+        (!(_ip##_VERSIONTYPE_##_to) ||                                 \
+         dwc->version_type <= _ip##_VERSIONTYPE_##_to))
+
 static inline int dwc3_host_init(struct dwc3 *dwc)
 { return 0; }
 static inline void dwc3_host_exit(struct dwc3 *dwc)
-- 
2.43.0

Reply via email to