* @test_mode: the selected test mode
  * @platdata: platform specific information supplied by parent device
  * @vbus_active: is VBUS active
- * @usb_phy: pointer to USB PHY, if any
+ * @phy: pointer to PHY, if any
+ * @usb_phy: pointer to USB PHY, if any and if using the USB PHY framework
  * @hcd: pointer to usb_hcd for ehci host driver
  * @debugfs: root dentry for this controller in debugfs
  * @id_event: indicates there is an id event, and handled at ci_otg_work
 
        struct ci_hdrc_platform_data    *platdata;
        int                             vbus_active;
+       struct phy                      *phy;
+       /* old usb_phy interface */
        struct usb_phy                  *usb_phy;
        struct usb_hcd                  *hcd;
        struct dentry                   *debugfs;
 
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
+#include <linux/phy/phy.h>
 #include <linux/platform_device.h>
 #include <linux/module.h>
 #include <linux/idr.h>
        }
 }
 
+/**
+ * _ci_usb_phy_init: initialize phy taking in account both phy and usb_phy
+ * interfaces
+ * @ci: the controller
+ *
+ * This function returns an error code if the phy failed to init
+ */
+static int _ci_usb_phy_init(struct ci_hdrc *ci)
+{
+       int ret;
+
+       if (ci->phy) {
+               ret = phy_init(ci->phy);
+               if (ret)
+                       return ret;
+
+               ret = phy_power_on(ci->phy);
+               if (ret) {
+                       phy_exit(ci->phy);
+                       return ret;
+               }
+       } else {
+               ret = usb_phy_init(ci->usb_phy);
+       }
+
+       return ret;
+}
+
+/**
+ * _ci_usb_phy_exit: deinitialize phy taking in account both phy and usb_phy
+ * interfaces
+ * @ci: the controller
+ */
+static void ci_usb_phy_exit(struct ci_hdrc *ci)
+{
+       if (ci->phy) {
+               phy_power_off(ci->phy);
+               phy_exit(ci->phy);
+       } else {
+               usb_phy_shutdown(ci->usb_phy);
+       }
+}
+
 /**
  * ci_usb_phy_init: initialize phy according to different phy type
  * @ci: the controller
        case USBPHY_INTERFACE_MODE_UTMI:
        case USBPHY_INTERFACE_MODE_UTMIW:
        case USBPHY_INTERFACE_MODE_HSIC:
-               ret = usb_phy_init(ci->usb_phy);
+               ret = _ci_usb_phy_init(ci);
                if (ret)
                        return ret;
                hw_phymode_configure(ci);
        case USBPHY_INTERFACE_MODE_ULPI:
        case USBPHY_INTERFACE_MODE_SERIAL:
                hw_phymode_configure(ci);
-               ret = usb_phy_init(ci->usb_phy);
+               ret = _ci_usb_phy_init(ci);
                if (ret)
                        return ret;
                break;
        default:
-               ret = usb_phy_init(ci->usb_phy);
+               ret = _ci_usb_phy_init(ci);
        }
 
        return ret;
                return -ENODEV;
        }
 
-       if (ci->platdata->usb_phy)
+       if (ci->platdata->phy) {
+               ci->phy = ci->platdata->phy;
+       } else if (ci->platdata->usb_phy) {
                ci->usb_phy = ci->platdata->usb_phy;
-       else
+       } else {
+               ci->phy = devm_phy_get(dev, "usb-phy");
                ci->usb_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
 
-       if (IS_ERR(ci->usb_phy)) {
-               ret = PTR_ERR(ci->usb_phy);
-               /*
-                * if -ENXIO is returned, it means PHY layer wasn't
-                * enabled, so it makes no sense to return -EPROBE_DEFER
-                * in that case, since no PHY driver will ever probe.
-                */
-               if (ret == -ENXIO)
-                       return ret;
+               /* if both generic PHY and USB PHY layers aren't enabled */
+               if (PTR_ERR(ci->phy) == -ENOSYS &&
+                               PTR_ERR(ci->usb_phy) == -ENXIO)
+                       return -ENXIO;
+
+               if (IS_ERR(ci->phy) && IS_ERR(ci->usb_phy))
+                       return -EPROBE_DEFER;
 
-               dev_err(dev, "no usb2 phy configured\n");
-               return -EPROBE_DEFER;
+               if (IS_ERR(ci->phy))
+                       ci->phy = NULL;
+               else if (IS_ERR(ci->usb_phy))
+                       ci->usb_phy = NULL;
        }
 
        ret = ci_usb_phy_init(ci);
 stop:
        ci_role_destroy(ci);
 deinit_phy:
-       usb_phy_shutdown(ci->usb_phy);
+       ci_usb_phy_exit(ci);
 
        return ret;
 }
        free_irq(ci->irq, ci);
        ci_role_destroy(ci);
        ci_hdrc_enter_lpm(ci, true);
-       usb_phy_shutdown(ci->usb_phy);
+       ci_usb_phy_exit(ci);
 
        return 0;
 }