usb: dwc3: gadget: Check for disabled LPM quirk
authorThinh Nguyen <Thinh.Nguyen@synopsys.com>
Wed, 14 Apr 2021 02:13:18 +0000 (19:13 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 11 May 2021 12:47:20 +0000 (14:47 +0200)
[ Upstream commit 475e8be53d0496f9bc6159f4abb3ff5f9b90e8de ]

If the device doesn't support LPM, make sure to disable the LPM
capability and don't advertise to the host that it supports it.

Acked-by: Felipe Balbi <balbi@kernel.org>
Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
Link: https://lore.kernel.org/r/9e68527ff932b1646f92a7593d4092a903754666.1618366071.git.Thinh.Nguyen@synopsys.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/usb/dwc3/core.c
drivers/usb/dwc3/core.h
drivers/usb/dwc3/gadget.c

index 3101f0d..1ffeb00 100644 (file)
@@ -1297,6 +1297,8 @@ static void dwc3_get_properties(struct dwc3 *dwc)
                                "snps,usb3_lpm_capable");
        dwc->usb2_lpm_disable = device_property_read_bool(dev,
                                "snps,usb2-lpm-disable");
+       dwc->usb2_gadget_lpm_disable = device_property_read_bool(dev,
+                               "snps,usb2-gadget-lpm-disable");
        device_property_read_u8(dev, "snps,rx-thr-num-pkt-prd",
                                &rx_thr_num_pkt_prd);
        device_property_read_u8(dev, "snps,rx-max-burst-prd",
index 1b241f9..575a93b 100644 (file)
@@ -1026,7 +1026,8 @@ struct dwc3_scratchpad_array {
  * @dis_start_transfer_quirk: set if start_transfer failure SW workaround is
  *                     not needed for DWC_usb31 version 1.70a-ea06 and below
  * @usb3_lpm_capable: set if hadrware supports Link Power Management
- * @usb2_lpm_disable: set to disable usb2 lpm
+ * @usb2_lpm_disable: set to disable usb2 lpm for host
+ * @usb2_gadget_lpm_disable: set to disable usb2 lpm for gadget
  * @disable_scramble_quirk: set if we enable the disable scramble quirk
  * @u2exit_lfps_quirk: set if we enable u2exit lfps quirk
  * @u2ss_inp3_quirk: set if we enable P3 OK for U2/SS Inactive quirk
@@ -1227,6 +1228,7 @@ struct dwc3 {
        unsigned                dis_start_transfer_quirk:1;
        unsigned                usb3_lpm_capable:1;
        unsigned                usb2_lpm_disable:1;
+       unsigned                usb2_gadget_lpm_disable:1;
 
        unsigned                disable_scramble_quirk:1;
        unsigned                u2exit_lfps_quirk:1;
index 5b55202..0ffd2a4 100644 (file)
@@ -3398,6 +3398,7 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
        /* Enable USB2 LPM Capability */
 
        if (!DWC3_VER_IS_WITHIN(DWC3, ANY, 194A) &&
+           !dwc->usb2_gadget_lpm_disable &&
            (speed != DWC3_DSTS_SUPERSPEED) &&
            (speed != DWC3_DSTS_SUPERSPEED_PLUS)) {
                reg = dwc3_readl(dwc->regs, DWC3_DCFG);
@@ -3424,6 +3425,12 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
 
                dwc3_gadget_dctl_write_safe(dwc, reg);
        } else {
+               if (dwc->usb2_gadget_lpm_disable) {
+                       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_HIRD_THRES_MASK;
                dwc3_gadget_dctl_write_safe(dwc, reg);
@@ -3871,7 +3878,7 @@ int dwc3_gadget_init(struct dwc3 *dwc)
        dwc->gadget->speed              = USB_SPEED_UNKNOWN;
        dwc->gadget->sg_supported       = true;
        dwc->gadget->name               = "dwc3-gadget";
-       dwc->gadget->lpm_capable        = true;
+       dwc->gadget->lpm_capable        = !dwc->usb2_gadget_lpm_disable;
 
        /*
         * FIXME We might be setting max_speed to <SUPER, however versions