summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Quadros <rogerq@kernel.org>2023-03-24 13:44:29 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-03-29 09:02:31 +0200
commit2926c5275028e44f6a2ac31b37d75d6d6e260306 (patch)
tree01f4112b41f48eac6277759eda27347c6af42e89
parentdb2c2b161d4a8f4a81e6f643848b1531517a67a5 (diff)
usb: dwc3-am62: Fix up wake-up configuration and spurious wake up
Explicitly set and clear wakeup config so we don't leave anything to chance. Clear wakeup status on suspend so we know what caused wake up. The LINESTATE wake up should not be enabled in device mode if we are not connected to a USB host and in USB suspend (U2/L3) else it will cause spurious wake up. For now, don't enable LINESTATE. This means wake up from USB resume will not work but at least we won't have any spurious wake ups. Signed-off-by: Roger Quadros <rogerq@kernel.org> Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com> Link: https://lore.kernel.org/r/20230324114429.21838-1-rogerq@kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/dwc3/dwc3-am62.c28
1 files changed, 18 insertions, 10 deletions
diff --git a/drivers/usb/dwc3/dwc3-am62.c b/drivers/usb/dwc3/dwc3-am62.c
index 859b48279658..b22fb78bc8e7 100644
--- a/drivers/usb/dwc3/dwc3-am62.c
+++ b/drivers/usb/dwc3/dwc3-am62.c
@@ -60,6 +60,13 @@
#define USBSS_WAKEUP_CFG_SESSVALID_EN BIT(1)
#define USBSS_WAKEUP_CFG_VBUSVALID_EN BIT(0)
+#define USBSS_WAKEUP_CFG_ALL (USBSS_WAKEUP_CFG_VBUSVALID_EN | \
+ USBSS_WAKEUP_CFG_SESSVALID_EN | \
+ USBSS_WAKEUP_CFG_LINESTATE_EN | \
+ USBSS_WAKEUP_CFG_OVERCURRENT_EN)
+
+#define USBSS_WAKEUP_CFG_NONE 0
+
/* WAKEUP STAT register bits */
#define USBSS_WAKEUP_STAT_OVERCURRENT BIT(4)
#define USBSS_WAKEUP_STAT_LINESTATE BIT(3)
@@ -103,6 +110,7 @@ struct dwc3_data {
struct regmap *syscon;
unsigned int offset;
unsigned int vbus_divider;
+ u32 wakeup_stat;
};
static const int dwc3_ti_rate_table[] = { /* in KHZ */
@@ -302,12 +310,17 @@ static int dwc3_ti_suspend_common(struct device *dev)
/* Set wakeup config enable bits */
reg = dwc3_ti_readl(data, USBSS_WAKEUP_CONFIG);
if (current_prtcap_dir == DWC3_GCTL_PRTCAP_HOST) {
- reg |= USBSS_WAKEUP_CFG_LINESTATE_EN | USBSS_WAKEUP_CFG_OVERCURRENT_EN;
+ reg = USBSS_WAKEUP_CFG_LINESTATE_EN | USBSS_WAKEUP_CFG_OVERCURRENT_EN;
} else {
- reg |= USBSS_WAKEUP_CFG_OVERCURRENT_EN | USBSS_WAKEUP_CFG_LINESTATE_EN |
- USBSS_WAKEUP_CFG_VBUSVALID_EN;
+ reg = USBSS_WAKEUP_CFG_VBUSVALID_EN | USBSS_WAKEUP_CFG_SESSVALID_EN;
+ /*
+ * Enable LINESTATE wake up only if connected to bus
+ * and in U2/L3 state else it causes spurious wake-up.
+ */
}
dwc3_ti_writel(data, USBSS_WAKEUP_CONFIG, reg);
+ /* clear wakeup status so we know what caused the wake up */
+ dwc3_ti_writel(data, USBSS_WAKEUP_STAT, USBSS_WAKEUP_STAT_CLR);
}
clk_disable_unprepare(data->usb2_refclk);
@@ -324,16 +337,11 @@ static int dwc3_ti_resume_common(struct device *dev)
if (device_may_wakeup(dev)) {
/* Clear wakeup config enable bits */
- reg = dwc3_ti_readl(data, USBSS_WAKEUP_CONFIG);
- reg &= ~(USBSS_WAKEUP_CFG_OVERCURRENT_EN | USBSS_WAKEUP_CFG_LINESTATE_EN |
- USBSS_WAKEUP_CFG_VBUSVALID_EN);
- dwc3_ti_writel(data, USBSS_WAKEUP_CONFIG, reg);
+ dwc3_ti_writel(data, USBSS_WAKEUP_CONFIG, USBSS_WAKEUP_CFG_NONE);
}
reg = dwc3_ti_readl(data, USBSS_WAKEUP_STAT);
- /* Clear the wakeup status with wakeup clear bit */
- reg |= USBSS_WAKEUP_STAT_CLR;
- dwc3_ti_writel(data, USBSS_WAKEUP_STAT, reg);
+ data->wakeup_stat = reg;
return 0;
}