usb: dwc2: disable external vbus supply when the device is removed
authorChristophe Kerello <christophe.kerello@st.com>
Thu, 15 Mar 2018 17:00:30 +0000 (18:00 +0100)
committerMarek Vasut <marex@denx.de>
Sat, 17 Mar 2018 02:23:09 +0000 (03:23 +0100)
This patch adds an interface to disable the power in dwc2 driver.
This new interface is called when the device is removed.

Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
drivers/usb/host/dwc2.c

index e436c711e720c143b312e455b0f232b11163efaf..138646e4c8f24b7e1269d5ac8fb22d68ab4bbd41 100644 (file)
@@ -34,6 +34,9 @@ struct dwc2_priv {
 #ifdef CONFIG_DM_USB
        uint8_t aligned_buffer[DWC2_DATA_BUF_SIZE] __aligned(ARCH_DMA_MINALIGN);
        uint8_t status_buffer[DWC2_STATUS_BUF_SIZE] __aligned(ARCH_DMA_MINALIGN);
+#ifdef CONFIG_DM_REGULATOR
+       struct udevice *vbus_supply;
+#endif
 #else
        uint8_t *aligned_buffer;
        uint8_t *status_buffer;
@@ -168,16 +171,17 @@ static void dwc_otg_core_reset(struct dwc2_core_regs *regs)
 #if defined(CONFIG_DM_USB) && defined(CONFIG_DM_REGULATOR)
 static int dwc_vbus_supply_init(struct udevice *dev)
 {
-       struct udevice *vbus_supply;
+       struct dwc2_priv *priv = dev_get_priv(dev);
        int ret;
 
-       ret = device_get_supply_regulator(dev, "vbus-supply", &vbus_supply);
+       ret = device_get_supply_regulator(dev, "vbus-supply",
+                                         &priv->vbus_supply);
        if (ret) {
                debug("%s: No vbus supply\n", dev->name);
                return 0;
        }
 
-       ret = regulator_set_enable(vbus_supply, true);
+       ret = regulator_set_enable(priv->vbus_supply, true);
        if (ret) {
                pr_err("Error enabling vbus supply\n");
                return ret;
@@ -185,11 +189,34 @@ static int dwc_vbus_supply_init(struct udevice *dev)
 
        return 0;
 }
+
+static int dwc_vbus_supply_exit(struct udevice *dev)
+{
+       struct dwc2_priv *priv = dev_get_priv(dev);
+       int ret;
+
+       if (priv->vbus_supply) {
+               ret = regulator_set_enable(priv->vbus_supply, false);
+               if (ret) {
+                       dev_err(dev, "Error disabling vbus supply\n");
+                       return ret;
+               }
+       }
+
+       return 0;
+}
 #else
 static int dwc_vbus_supply_init(struct udevice *dev)
 {
        return 0;
 }
+
+#if defined(CONFIG_DM_USB)
+static int dwc_vbus_supply_exit(struct udevice *dev)
+{
+       return 0;
+}
+#endif
 #endif
 
 /*
@@ -1269,6 +1296,11 @@ static int dwc2_usb_probe(struct udevice *dev)
 static int dwc2_usb_remove(struct udevice *dev)
 {
        struct dwc2_priv *priv = dev_get_priv(dev);
+       int ret;
+
+       ret = dwc_vbus_supply_exit(dev);
+       if (ret)
+               return ret;
 
        dwc2_uninit_common(priv->regs);