From: Mehmet Fide <[email protected]>

The driver never enables the vbus-supply of its port, so on boards that
switch VBUS through a regulator, such as the Colibri VF50 and VF61
carriers, the port stays unpowered and no device is found.

Do what ehci-mx6 does: look the regulator up in probe, enable it in
host mode, disable it in device mode, and turn it off on remove. A
missing vbus-supply or a build without DM_REGULATOR is fine; any other
lookup error fails the probe instead of leaving the port dead.

Signed-off-by: Mehmet Fide <[email protected]>
---

Notes:
    Changes in v8:
    - the two includes go in sorted, and the reset hook keeps its argument
      name dev (Marek)
    
    Changes in v7:
    - the Reviewed-by of Marek and Simon on v6 is dropped: the VBUS code is
      unchanged, but the remove hook now comes from patch 7 and this patch
      adds its VBUS line to it
    
    Changes in v6:
    - dev_err() and dev_dbg() for the two messages; the reset hook reaches
      the device through the private data
    
    Changes in v5:
    - none
    
    Changes in v4:
    - enable VBUS in the reset hook only, as ehci-mx6 does: enabling it in
      the shared init as well counted two enables per probe, so "usb stop"
      never switched it off
    - the dm core patch it needed is dropped, next claims the regulator
      GPIO at probe time
    - reworded the commit message

 drivers/usb/host/ehci-vf.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/drivers/usb/host/ehci-vf.c b/drivers/usb/host/ehci-vf.c
index 81f76ddb1ba..f5c6eae6779 100644
--- a/drivers/usb/host/ehci-vf.c
+++ b/drivers/usb/host/ehci-vf.c
@@ -17,9 +17,11 @@
 #include <asm/io.h>
 #include <asm/mach-imx/iomux-v3.h>
 #include <asm/mach-imx/regs-usbphy.h>
+#include <dm/device_compat.h>
 #include <linux/compiler.h>
 #include <linux/delay.h>
 #include <linux/usb/otg.h>
+#include <power/regulator.h>
 #include <usb/ehci-ci.h>
 
 #include "ehci.h"
@@ -42,6 +44,8 @@ struct ehci_vf_priv_data {
        struct anadig_reg __iomem *anatop_addr;
        void __iomem *phy_addr;
        void __iomem *misc_addr;
+       struct udevice *vbus_supply;
+       struct udevice *dev;
        u32 portnr;
 };
 
@@ -230,6 +234,13 @@ static int vf_init_after_reset(struct ehci_ctrl *dev)
        if (ret)
                return ret;
 
+       ret = regulator_set_enable_if_allowed(priv->vbus_supply,
+                                             type != USB_INIT_DEVICE);
+       if (ret && ret != -ENOSYS) {
+               dev_err(priv->dev, "cannot enable the VBUS supply: %d\n", ret);
+               return ret;
+       }
+
        if (type == USB_INIT_DEVICE)
                return 0;
 
@@ -255,6 +266,16 @@ static int ehci_usb_probe(struct udevice *dev)
        struct ehci_hcor *hcor;
        int ret;
 
+       priv->dev = dev;
+       ret = device_get_supply_regulator(dev, "vbus-supply",
+                                         &priv->vbus_supply);
+       if (ret == -ENOENT || ret == -ENOSYS) {
+               dev_dbg(dev, "no VBUS supply\n");
+       } else if (ret) {
+               dev_err(dev, "cannot get the VBUS supply: %d\n", ret);
+               return ret;
+       }
+
        if (priv->dr_mode == USB_DR_MODE_OTG) {
                ret = gpio_request_by_name(dev, "fsl,cdet-gpio", 0,
                                           &priv->cdet_gpio, GPIOD_IS_IN);
@@ -311,6 +332,8 @@ static int ehci_usb_remove(struct udevice *dev)
 {
        struct ehci_vf_priv_data *priv = dev_get_priv(dev);
 
+       regulator_set_enable_if_allowed(priv->vbus_supply, false);
+
        if (dm_gpio_is_valid(&priv->cdet_gpio))
                dm_gpio_free(dev, &priv->cdet_gpio);
 
-- 
2.55.0

Reply via email to