mirror of
https://github.com/Fishwaldo/build.git
synced 2025-03-26 00:31:47 +00:00
68 lines
2.2 KiB
Diff
68 lines
2.2 KiB
Diff
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
|
|
index cc9c93af..3ff41d87 100644
|
|
--- a/drivers/usb/dwc2/core.h
|
|
+++ b/drivers/usb/dwc2/core.h
|
|
@@ -1021,6 +1021,7 @@ struct dwc2_hsotg {
|
|
u16 frame_number;
|
|
|
|
struct phy *phy;
|
|
+ struct work_struct phy_rst_work;
|
|
struct usb_phy *uphy;
|
|
struct dwc2_hsotg_plat *plat;
|
|
struct regulator_bulk_data supplies[DWC2_NUM_SUPPLIES];
|
|
diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
|
|
index 19ae2595..f1270bf1 100644
|
|
--- a/drivers/usb/dwc2/core_intr.c
|
|
+++ b/drivers/usb/dwc2/core_intr.c
|
|
@@ -396,6 +396,7 @@ static void dwc2_wakeup_from_lpm_l1(struct dwc2_hsotg *hsotg)
|
|
static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
|
|
{
|
|
int ret;
|
|
+ struct device_node *np = hsotg->dev->of_node;
|
|
|
|
/* Clear interrupt */
|
|
dwc2_writel(hsotg, GINTSTS_WKUPINT, GINTSTS);
|
|
@@ -435,6 +436,16 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
|
|
/* Restart the Phy Clock */
|
|
pcgcctl &= ~PCGCTL_STOPPCLK;
|
|
dwc2_writel(hsotg, pcgcctl, PCGCTL);
|
|
+
|
|
+ /*
|
|
+ * It is a quirk in Rockchip RK3288, causing by
|
|
+ * a hardware bug. This will propagate out and
|
|
+ * eventually we'll re-enumerate the device.
|
|
+ * Not great but the best we can do.
|
|
+ */
|
|
+ if (of_device_is_compatible(np, "rockchip,rk3288-usb"))
|
|
+ schedule_work(&hsotg->phy_rst_work);
|
|
+
|
|
mod_timer(&hsotg->wkp_timer,
|
|
jiffies + msecs_to_jiffies(71));
|
|
} else {
|
|
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
|
|
index 57764289..748763bd 100644
|
|
--- a/drivers/usb/dwc2/platform.c
|
|
+++ b/drivers/usb/dwc2/platform.c
|
|
@@ -208,6 +208,14 @@ int dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg)
|
|
return ret;
|
|
}
|
|
|
|
+/* Only used to reset usb phy at interrupter runtime */
|
|
+static void dwc2_reset_phy_work(struct work_struct *data)
|
|
+{
|
|
+ struct dwc2_hsotg *hsotg = container_of(data, struct dwc2_hsotg,
|
|
+ phy_rst_work);
|
|
+ phy_reset(hsotg->phy);
|
|
+}
|
|
+
|
|
static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg)
|
|
{
|
|
int i, ret;
|
|
@@ -252,6 +260,7 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg)
|
|
return ret;
|
|
}
|
|
}
|
|
+ INIT_WORK(&hsotg->phy_rst_work, dwc2_reset_phy_work);
|
|
|
|
if (!hsotg->phy) {
|
|
hsotg->uphy = devm_usb_get_phy(hsotg->dev, USB_PHY_TYPE_USB2);
|