Merge "Update EdgeTPU PCIe registers in the device tree"
diff --git a/drivers/soc/imx/gpc-psci.c b/drivers/soc/imx/gpc-psci.c
index d3867e1..0505bce 100644
--- a/drivers/soc/imx/gpc-psci.c
+++ b/drivers/soc/imx/gpc-psci.c
@@ -52,6 +52,9 @@
 static DEFINE_SPINLOCK(gpc_psci_lock);
 static DEFINE_MUTEX(gpc_pd_mutex);
 
+/* USB1 port power domain */
+static bool usb1_on = false;
+
 static void imx_gpc_psci_irq_unmask(struct irq_data *d)
 {
 	struct arm_smccc_res res;
@@ -202,6 +205,9 @@
 	struct arm_smccc_res res;
 	int index, ret = 0;
 
+	if (usb1_on && pd->gpc_domain_id == 3)
+		return 0;
+
 	/* power on the external supply */
 	if (pd->reg) {
 		ret = regulator_enable(pd->reg);
@@ -222,6 +228,9 @@
 		      GPC_PD_STATE_ON, 0, 0, 0, 0, &res);
 	mutex_unlock(&gpc_pd_mutex);
 
+	if (pd->gpc_domain_id == 3)
+		usb1_on = true;
+
 	return 0;
 }
 
@@ -231,6 +240,9 @@
 	struct arm_smccc_res res;
 	int index, ret = 0;
 
+	if (pd->gpc_domain_id == 3)
+		return 0;
+
 	mutex_lock(&gpc_pd_mutex);
 	arm_smccc_smc(FSL_SIP_GPC, FSL_SIP_CONFIG_GPC_PM_DOMAIN, pd->gpc_domain_id,
 		      GPC_PD_STATE_OFF, 0, 0, 0, 0, &res);
diff --git a/drivers/soc/imx/sc/main/ipc.c b/drivers/soc/imx/sc/main/ipc.c
index c070089..be1e265 100644
--- a/drivers/soc/imx/sc/main/ipc.c
+++ b/drivers/soc/imx/sc/main/ipc.c
@@ -7,6 +7,7 @@
 
 /* Includes */
 #include <linux/arm-smccc.h>
+#include <linux/completion.h>
 #include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/of.h>
@@ -18,6 +19,7 @@
 #include <linux/irq.h>
 #include <linux/mx8_mu.h>
 #include <linux/syscore_ops.h>
+#include <linux/suspend.h>
 
 #include <soc/imx/fsl_hvc.h>
 #include <soc/imx8/sc/svc/irq/api.h>
@@ -39,7 +41,9 @@
 
 /* Local variables */
 static uint32_t gIPCport;
+static sc_rpc_msg_t *rx_msg;
 static bool scu_mu_init;
+struct completion rx_completion;
 
 DEFINE_MUTEX(scu_mu_mutex);
 
@@ -57,6 +61,7 @@
 void sc_call_rpc(sc_ipc_t handle, sc_rpc_msg_t *msg, sc_bool_t no_resp)
 {
 	struct arm_smccc_res res;
+	unsigned long timeout;
 
 	if (in_interrupt()) {
 		pr_warn("Cannot make SC IPC calls from an interrupt context\n");
@@ -65,6 +70,8 @@
 	}
 	mutex_lock(&scu_mu_mutex);
 
+	reinit_completion(&rx_completion);
+	rx_msg = msg;
 	if (xen_initial_domain()) {
 		arm_smccc_hvc(FSL_HVC_SC, (uint64_t)msg, no_resp, 0, 0, 0, 0,
 			      0, &res);
@@ -72,8 +79,14 @@
 			printk("Error FSL_HVC_SC %ld\n", res.a0);
 	} else {
 		sc_ipc_write(handle, msg);
-		if (!no_resp)
-			sc_ipc_read(handle, msg);
+		if (!no_resp) {
+			timeout = wait_for_completion_timeout(&rx_completion, HZ / 10);
+			if (!timeout) {
+				pr_err("Timeout for IPC response!\n");
+				mutex_unlock(&scu_mu_mutex);
+				return;
+			}
+		}
 	}
 
 	mutex_unlock(&scu_mu_mutex);
@@ -285,12 +298,19 @@
 {
 	u32 irqs;
 
+	irqs = (readl_relaxed(mu_base_virtaddr + 0x20) & (0xf << 24));
+	if (irqs) {
+		sc_ipc_read(mu_ipcHandle, rx_msg);
+		complete(&rx_completion);
+	}
+
 	irqs = (readl_relaxed(mu_base_virtaddr + 0x20) & (0xf << 28));
 	if (irqs) {
 		/* Clear the General Interrupt */
 		writel_relaxed(irqs, mu_base_virtaddr + 0x20);
 		/* Setup a bottom-half to handle the irq work. */
 		schedule_delayed_work(&scu_mu_work, 0);
+		pm_system_wakeup();
 	}
 	return IRQ_HANDLED;
 }
@@ -300,6 +320,7 @@
 	int i;
 
 	MU_Init(mu_base_virtaddr);
+	MU_EnableRxFullInt(mu_base_virtaddr, 0);
 	for (i = 0; i < MU_RR_COUNT; i++)
 		MU_EnableGeneralInt(mu_base_virtaddr, i);
 }
@@ -338,7 +359,7 @@
 		pr_warn("imx8_mu_init: no irq: %d\n", irq);
 	} else {
 		err = request_irq(irq, imx8_scu_mu_isr,
-				  IRQF_EARLY_RESUME, "imx8_mu_isr", NULL);
+				  IRQF_NO_SUSPEND, "imx8_mu_isr", NULL);
 		if (err) {
 			pr_err("imx8_mu_init: request_irq %d failed: %d\n",
 					irq, err);
@@ -355,6 +376,7 @@
 
 		/* Init MU */
 		MU_Init(mu_base_virtaddr);
+		MU_EnableRxFullInt(mu_base_virtaddr, 0);
 
 #if 1
 		/* Enable all RX interrupts */
@@ -363,6 +385,7 @@
 #endif
 		gIPCport = scu_mu_id;
 		scu_mu_init = true;
+		init_completion(&rx_completion);
 	}
 
 	sciErr = sc_ipc_open(&mu_ipcHandle, scu_mu_id);
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 090c864..f7e0891 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -45,6 +45,7 @@
 #define DWC3_EP0_SETUP_SIZE	512
 #define DWC3_ENDPOINTS_NUM	32
 #define DWC3_XHCI_RESOURCES_NUM	2
+#define DWC3_ISOC_MAX_RETRIES	5
 
 #define DWC3_SCRATCHBUF_SIZE	4096	/* each buffer is assumed to be 4KiB */
 #define DWC3_EVENT_BUFFERS_SIZE	4096
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 9d91a8c..23d461a 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -36,6 +36,9 @@
 #include "gadget.h"
 #include "io.h"
 
+#define DWC3_ALIGN_FRAME(d, uf, n) ((uf + ((d)->interval * (n))) \
+				    & ~((d)->interval - 1))
+
 /**
  * dwc3_gadget_set_test_mode - enables usb2 test modes
  * @dwc: pointer to our context structure
@@ -1272,7 +1275,7 @@
 static void __dwc3_gadget_start_isoc(struct dwc3 *dwc,
 		struct dwc3_ep *dep, u32 cur_uf)
 {
-	u32 uf;
+	int ret, i;
 
 	if (list_empty(&dep->pending_list)) {
 		dev_info(dwc->dev, "%s: ran out of requests\n",
@@ -1281,13 +1284,13 @@
 		return;
 	}
 
-	/*
-	 * Schedule the first trb for one interval in the future or at
-	 * least 4 microframes.
-	 */
-	uf = cur_uf + max_t(u32, 4, dep->interval);
-
-	__dwc3_gadget_kick_transfer(dep, uf);
+	for (i = 0; i < DWC3_ISOC_MAX_RETRIES; i++) {
+		/* always start isochronous aligned to dep->interval */
+		cur_uf = DWC3_ALIGN_FRAME(dep, cur_uf, i + 1);
+		ret = __dwc3_gadget_kick_transfer(dep, cur_uf);
+		if (ret != -EAGAIN)
+			break;
+	}
 }
 
 static void dwc3_gadget_start_isoc(struct dwc3 *dwc,
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index eaed46b..2d56c1e 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -301,6 +301,7 @@
 	if (ret)
 		goto dealloc_usb2_hcd;
 
+	device_set_wakeup_capable(&pdev->dev, true);
 	device_enable_async_suspend(&pdev->dev);
 	pm_runtime_put_noidle(&pdev->dev);
 
@@ -364,7 +365,7 @@
 {
 	struct usb_hcd	*hcd = dev_get_drvdata(dev);
 	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
-
+#if 0
 	/*
 	 * xhci_suspend() needs `do_wakeup` to know whether host is allowed
 	 * to do wakeup during suspend. Since xhci_plat_suspend is currently
@@ -374,6 +375,11 @@
 	 * also applies to runtime suspend.
 	 */
 	return xhci_suspend(xhci, device_may_wakeup(dev));
+#endif
+	if (device_may_wakeup(dev))
+		enable_irq_wake(hcd->irq);
+
+	return 0;
 }
 
 static int __maybe_unused xhci_plat_resume(struct device *dev)
@@ -382,11 +388,17 @@
 	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
 	int ret;
 
+#if 0
 	ret = xhci_priv_resume_quirk(hcd);
 	if (ret)
 		return ret;
 
 	return xhci_resume(xhci, 0);
+#endif
+	if (device_may_wakeup(dev))
+		disable_irq_wake(hcd->irq);
+
+	return 0;
 }
 
 static int __maybe_unused xhci_plat_runtime_suspend(struct device *dev)