menu "USB Physical Layer drivers"
 
 config USB_PHY
+       select EXTCON
        def_bool n
 
 #
 
 config TAHVO_USB
        tristate "Tahvo USB transceiver driver"
-       depends on MFD_RETU && EXTCON
+       depends on MFD_RETU
        depends on USB_GADGET || !USB_GADGET # if USB_GADGET=m, this can't be 'y'
        select USB_PHY
        help
        depends on (USB || USB_GADGET) && (ARCH_QCOM || COMPILE_TEST)
        depends on USB_GADGET || !USB_GADGET # if USB_GADGET=m, this can't be 'y'
        depends on RESET_CONTROLLER
-       depends on EXTCON
        select USB_PHY
        help
          Enable this to support the USB OTG transceiver on Qualcomm chips. It
 config USB_QCOM_8X16_PHY
        tristate "Qualcomm APQ8016/MSM8916 on-chip USB PHY controller support"
        depends on ARCH_QCOM || COMPILE_TEST
-       depends on RESET_CONTROLLER && EXTCON
+       depends on RESET_CONTROLLER
        select USB_PHY
        select USB_ULPI_VIEWPORT
        help
 
        return *phy == match_data;
 }
 
+static int usb_add_extcon(struct usb_phy *x)
+{
+       int ret;
+
+       if (of_property_read_bool(x->dev->of_node, "extcon")) {
+               x->edev = extcon_get_edev_by_phandle(x->dev, 0);
+               if (IS_ERR(x->edev))
+                       return PTR_ERR(x->edev);
+
+               x->id_edev = extcon_get_edev_by_phandle(x->dev, 1);
+               if (IS_ERR(x->id_edev)) {
+                       x->id_edev = NULL;
+                       dev_info(x->dev, "No separate ID extcon device\n");
+               }
+
+               if (x->vbus_nb.notifier_call) {
+                       ret = devm_extcon_register_notifier(x->dev, x->edev,
+                                                           EXTCON_USB,
+                                                           &x->vbus_nb);
+                       if (ret < 0) {
+                               dev_err(x->dev,
+                                       "register VBUS notifier failed\n");
+                               return ret;
+                       }
+               }
+
+               if (x->id_nb.notifier_call) {
+                       struct extcon_dev *id_ext;
+
+                       if (x->id_edev)
+                               id_ext = x->id_edev;
+                       else
+                               id_ext = x->edev;
+
+                       ret = devm_extcon_register_notifier(x->dev, id_ext,
+                                                           EXTCON_USB_HOST,
+                                                           &x->id_nb);
+                       if (ret < 0) {
+                               dev_err(x->dev,
+                                       "register ID notifier failed\n");
+                               return ret;
+                       }
+               }
+       }
+
+       return 0;
+}
+
 /**
  * devm_usb_get_phy - find the USB PHY
  * @dev - device that requests this phy
                return -EINVAL;
        }
 
+       ret = usb_add_extcon(x);
+       if (ret)
+               return ret;
+
        ATOMIC_INIT_NOTIFIER_HEAD(&x->notifier);
 
        spin_lock_irqsave(&phy_lock, flags);
 {
        struct usb_phy_bind *phy_bind;
        unsigned long flags;
+       int ret;
 
        if (!x->dev) {
                dev_err(x->dev, "no device provided for PHY\n");
                return -EINVAL;
        }
 
+       ret = usb_add_extcon(x);
+       if (ret)
+               return ret;
+
        ATOMIC_INIT_NOTIFIER_HEAD(&x->notifier);
 
        spin_lock_irqsave(&phy_lock, flags);
 
 #ifndef __LINUX_USB_PHY_H
 #define __LINUX_USB_PHY_H
 
+#include <linux/extcon.h>
 #include <linux/notifier.h>
 #include <linux/usb.h>
 
        struct usb_phy_io_ops   *io_ops;
        void __iomem            *io_priv;
 
+       /* to support extcon device */
+       struct extcon_dev       *edev;
+       struct extcon_dev       *id_edev;
+       struct notifier_block   vbus_nb;
+       struct notifier_block   id_nb;
+
        /* for notification of usb_phy_events */
        struct atomic_notifier_head     notifier;