]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
usb: dwc3: add lpm erratum support
authorHuang Rui <ray.huang@amd.com>
Tue, 28 Oct 2014 11:54:26 +0000 (19:54 +0800)
committerFelipe Balbi <balbi@ti.com>
Mon, 3 Nov 2014 16:03:36 +0000 (10:03 -0600)
When parameter DWC_USB3_LPM_ERRATA_ENABLE is enabled in Andvanced
Configuration of coreConsultant, it supports of xHCI BESL Errata Dated
10/19/2011 is enabled in host mode. In device mode it adds the capability
to send NYET response threshold based on the BESL value received in the LPM
token, and the threhold is configurable for each soc platform.

This patch adds an entry that soc platform is able to define the lpm
capacity with their own device tree or bus glue layer.

[ balbi@ti.com : added devicetree documentation, spelled threshold
completely, made sure threshold is only applied to
proper core revisions. ]

Signed-off-by: Huang Rui <ray.huang@amd.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Documentation/devicetree/bindings/usb/dwc3.txt
drivers/usb/dwc3/core.c
drivers/usb/dwc3/core.h
drivers/usb/dwc3/gadget.c
drivers/usb/dwc3/platform_data.h

index 8ec2256a4a09f0b72112dd682373d9745b8dcaeb..2b0c1f2e6e27a1f99003154efd42c37e563044a0 100644 (file)
@@ -16,6 +16,8 @@ Optional properties:
  - tx-fifo-resize: determines if the FIFO *has* to be reallocated.
  - snps,disable_scramble_quirk: true when SW should disable data scrambling.
        Only really useful for FPGA builds.
+ - snps,has-lpm-erratum: true when DWC3 was configured with LPM Erratum enabled
+ - snps,lpm-nyet-threshold: LPM NYET threshold
 
 This is usually a subnode to DWC3 glue to which it is connected.
 
index a0ae1326b7e3ca7c01d6113eeb7f17bebcbe3fb4..6f9e5b85977ae097b83d7b7efd9f2ee32b598ef5 100644 (file)
@@ -657,6 +657,7 @@ static int dwc3_probe(struct platform_device *pdev)
        struct device_node      *node = dev->of_node;
        struct resource         *res;
        struct dwc3             *dwc;
+       u8                      lpm_nyet_threshold;
 
        int                     ret;
 
@@ -712,16 +713,27 @@ static int dwc3_probe(struct platform_device *pdev)
         */
        res->start -= DWC3_GLOBALS_REGS_START;
 
+       /* default to highest possible threshold */
+       lpm_nyet_threshold = 0xff;
+
        if (node) {
                dwc->maximum_speed = of_usb_get_maximum_speed(node);
+               dwc->has_lpm_erratum = of_property_read_bool(node,
+                               "snps,has-lpm-erratum");
+               of_property_read_u8(node, "snps,lpm-nyet-threshold",
+                               &lpm_nyet_threshold);
 
-               dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
+               dwc->needs_fifo_resize = of_property_read_bool(node,
+                               "tx-fifo-resize");
                dwc->dr_mode = of_usb_get_dr_mode(node);
 
                dwc->disable_scramble_quirk = of_property_read_bool(node,
                                "snps,disable_scramble_quirk");
        } else if (pdata) {
                dwc->maximum_speed = pdata->maximum_speed;
+               dwc->has_lpm_erratum = pdata->has_lpm_erratum;
+               if (pdata->lpm_nyet_threshold)
+                       lpm_nyet_threshold = pdata->lpm_nyet_threshold;
 
                dwc->needs_fifo_resize = pdata->tx_fifo_resize;
                dwc->dr_mode = pdata->dr_mode;
@@ -733,6 +745,8 @@ static int dwc3_probe(struct platform_device *pdev)
        if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
                dwc->maximum_speed = USB_SPEED_SUPER;
 
+       dwc->lpm_nyet_threshold = lpm_nyet_threshold;
+
        ret = dwc3_core_get_phy(dwc);
        if (ret)
                return ret;
index 56bada6c8604a304a35746be421a774bbf92cbb3..34f1e08988fefe683965f0a160fcc356e41583eb 100644 (file)
 #define DWC3_DCTL_TRGTULST_SS_INACT    (DWC3_DCTL_TRGTULST(6))
 
 /* These apply for core versions 1.94a and later */
-#define DWC3_DCTL_KEEP_CONNECT (1 << 19)
-#define DWC3_DCTL_L1_HIBER_EN  (1 << 18)
-#define DWC3_DCTL_CRS          (1 << 17)
-#define DWC3_DCTL_CSS          (1 << 16)
+#define DWC3_DCTL_LPM_ERRATA_MASK      DWC3_DCTL_LPM_ERRATA(0xf)
+#define DWC3_DCTL_LPM_ERRATA(n)                ((n) << 20)
 
-#define DWC3_DCTL_INITU2ENA    (1 << 12)
-#define DWC3_DCTL_ACCEPTU2ENA  (1 << 11)
-#define DWC3_DCTL_INITU1ENA    (1 << 10)
-#define DWC3_DCTL_ACCEPTU1ENA  (1 << 9)
-#define DWC3_DCTL_TSTCTRL_MASK (0xf << 1)
+#define DWC3_DCTL_KEEP_CONNECT         (1 << 19)
+#define DWC3_DCTL_L1_HIBER_EN          (1 << 18)
+#define DWC3_DCTL_CRS                  (1 << 17)
+#define DWC3_DCTL_CSS                  (1 << 16)
+
+#define DWC3_DCTL_INITU2ENA            (1 << 12)
+#define DWC3_DCTL_ACCEPTU2ENA          (1 << 11)
+#define DWC3_DCTL_INITU1ENA            (1 << 10)
+#define DWC3_DCTL_ACCEPTU1ENA          (1 << 9)
+#define DWC3_DCTL_TSTCTRL_MASK         (0xf << 1)
 
 #define DWC3_DCTL_ULSTCHNGREQ_MASK     (0x0f << 5)
 #define DWC3_DCTL_ULSTCHNGREQ(n) (((n) << 5) & DWC3_DCTL_ULSTCHNGREQ_MASK)
@@ -660,10 +663,13 @@ struct dwc3_scratchpad_array {
  * @regset: debugfs pointer to regdump file
  * @test_mode: true when we're entering a USB test mode
  * @test_mode_nr: test feature selector
+ * @lpm_nyet_threshold: LPM NYET response threshold
  * @delayed_status: true when gadget driver asks for delayed status
  * @ep0_bounced: true when we used bounce buffer
  * @ep0_expect_in: true when we expect a DATA IN transfer
  * @has_hibernation: true when dwc3 was configured with Hibernation
+ * @has_lpm_erratum: true when core was configured with LPM Erratum. Note that
+ *                     there's now way for software to detect this in runtime.
  * @is_selfpowered: true when we are selfpowered
  * @is_fpga: true when we are using the FPGA board
  * @needs_fifo_resize: not all users might want fifo resizing, flag it
@@ -764,11 +770,13 @@ struct dwc3 {
 
        u8                      test_mode;
        u8                      test_mode_nr;
+       u8                      lpm_nyet_threshold;
 
        unsigned                delayed_status:1;
        unsigned                ep0_bounced:1;
        unsigned                ep0_expect_in:1;
        unsigned                has_hibernation:1;
+       unsigned                has_lpm_erratum:1;
        unsigned                is_selfpowered:1;
        unsigned                is_fpga:1;
        unsigned                needs_fifo_resize:1;
index 20dda60b27c309c2948cdfbfa384fa3550006af3..88a065f611504b232d9b6429d01b8e09db945bb8 100644 (file)
@@ -2301,6 +2301,19 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
                 */
                reg |= DWC3_DCTL_HIRD_THRES(12);
 
+               /*
+                * When dwc3 revisions >= 2.40a, LPM Erratum is enabled and
+                * DCFG.LPMCap is set, core responses with an ACK and the
+                * BESL value in the LPM token is less than or equal to LPM
+                * NYET threshold.
+                */
+               WARN_ONCE(dwc->revision < DWC3_REVISION_240A
+                               && dwc->has_lpm_erratum,
+                               "LPM Erratum not available on dwc3 revisisions < 2.40a\n");
+
+               if (dwc->has_lpm_erratum && dwc->revision >= DWC3_REVISION_240A)
+                       reg |= DWC3_DCTL_LPM_ERRATA(dwc->lpm_nyet_threshold);
+
                dwc3_writel(dwc->regs, DWC3_DCTL, reg);
        } else {
                reg = dwc3_readl(dwc->regs, DWC3_DCTL);
index 9209d025597b50ee3e3fee3f2dc79073cd4f1a42..e1283080a49fc07a499a282641a61589f140dad5 100644 (file)
@@ -25,5 +25,8 @@ struct dwc3_platform_data {
        enum usb_dr_mode dr_mode;
        bool tx_fifo_resize;
 
+       u8 lpm_nyet_threshold;
+
        unsigned disable_scramble_quirk:1;
+       unsigned has_lpm_erratum:1;
 };