Add TPU power cycle support

In some cases, TPU loses its USB link after excessive resets. The USB
driver tries to power cycle the port to recover the device, but the
platform driver needs to actually implement the power cycle.

This does not resolve the potential losing link condition during the TPU engine
initialization, but the TPU is recovered back to the DFU mode ready for the
next trial.

Bug: 162766719
Change-Id: If27a56bc8a138f326231a7193fb9b817453ee06e
diff --git a/arch/arm64/boot/dts/mediatek/mt8167-coral.dts b/arch/arm64/boot/dts/mediatek/mt8167-coral.dts
index bae1e0d..b759fc4 100644
--- a/arch/arm64/boot/dts/mediatek/mt8167-coral.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8167-coral.dts
@@ -50,7 +50,6 @@
 		gpio = <&pio 56 GPIO_ACTIVE_HIGH>;
 		startup-delay-us = <0>;
 		enable-active-high;
-		regulator-always-on;
 	};
 	ga1600_reset: ga1600_reset {
 		compatible = "regulator-fixed";
@@ -632,4 +631,5 @@
 
 &usb1 {
 	status = "okay";
+	ga1600_pmic-supply = <&ga1600_pmic>;
 };
diff --git a/drivers/misc/mediatek/usb11/Kconfig b/drivers/misc/mediatek/usb11/Kconfig
index 6bfdfae..d1a5cad 100644
--- a/drivers/misc/mediatek/usb11/Kconfig
+++ b/drivers/misc/mediatek/usb11/Kconfig
@@ -55,3 +55,8 @@
 	  (eg: 500ma), OCP pin will protect, disable Power, then will
 	  resume.
 	  It depends the OCP HW and the design.
+
+config EDGETPU_PMIC_SUPPORT
+	bool "EdgeTPU pmic support"
+	---help---
+		Say Y here if EDGTPU uses USB link but PMIC is controlled separately.
diff --git a/drivers/misc/mediatek/usb11/mt8167/musbfsh_core.c b/drivers/misc/mediatek/usb11/mt8167/musbfsh_core.c
index fff3906..23777dd 100644
--- a/drivers/misc/mediatek/usb11/mt8167/musbfsh_core.c
+++ b/drivers/misc/mediatek/usb11/mt8167/musbfsh_core.c
@@ -1336,6 +1336,7 @@
 	struct musbfsh *musbfsh;
 	struct musbfsh_hdrc_platform_data *plat = dev->platform_data;
 	struct usb_hcd *hcd;
+	struct regulator *vbus_supply = NULL;
 
 	INFO("++\n");
 	/* The driver might handle more features than the board; OK.
@@ -1363,6 +1364,14 @@
 
 	musbfsh->config->fifo_cfg = epx_cfg;
 	musbfsh->config->fifo_cfg_size = sizeof(epx_cfg) / sizeof(struct musbfsh_fifo_cfg);
+
+#ifdef CONFIG_EDGETPU_PMIC_SUPPORT
+	vbus_supply = devm_regulator_get_optional(dev, "ga1600_pmic");
+	if (vbus_supply) {
+		musbfsh->vbus_supply = vbus_supply;
+		WARNING("vbus registered\n");
+	}
+#endif
 	/* The musbfsh_platform_init() call:
 	 *   - adjusts musbfsh->mregs and musbfsh->isr if needed,
 	 *   - may initialize an integrated tranceiver
diff --git a/drivers/misc/mediatek/usb11/mt8167/musbfsh_core.h b/drivers/misc/mediatek/usb11/mt8167/musbfsh_core.h
index 9c1361b..98b6cd2 100644
--- a/drivers/misc/mediatek/usb11/mt8167/musbfsh_core.h
+++ b/drivers/misc/mediatek/usb11/mt8167/musbfsh_core.h
@@ -335,6 +335,7 @@
 	struct delayed_work p1_cldet_pin_work;
 	struct delayed_work p2_cldet_pin_work;
 #endif
+	struct regulator *vbus_supply;
 };
 
 static inline void musbfsh_configure_ep0(struct musbfsh *musbfsh)
diff --git a/drivers/misc/mediatek/usb11/mt8167/musbfsh_mt65xx.c b/drivers/misc/mediatek/usb11/mt8167/musbfsh_mt65xx.c
index b112a8a..cfe4058 100644
--- a/drivers/misc/mediatek/usb11/mt8167/musbfsh_mt65xx.c
+++ b/drivers/misc/mediatek/usb11/mt8167/musbfsh_mt65xx.c
@@ -443,7 +443,27 @@
 
 void mt_usb11_set_vbus(struct musbfsh *musbfsh, int is_on)
 {
+	int ret;
 	INFO("is_on=%d\n", is_on);
+#ifdef CONFIG_EDGETPU_PMIC_SUPPORT
+	if (musbfsh->vbus_supply) {
+		if (is_on) {
+			ret = regulator_enable(musbfsh->vbus_supply);
+			if (ret) {
+				ERR("Failed to enable VBUS\n");
+			} else {
+				WARNING("Enable VBUS\n");
+			}
+		} else {
+			ret = regulator_disable(musbfsh->vbus_supply);
+			if (ret) {
+				ERR("Failed to disable VBUS\n");
+			} else {
+				WARNING("Disable VBUS\n");
+			}
+		}
+	}
+#endif
 }
 
 void musbfs_check_mpu_violation(u32 addr, int wr_vio)