writeb(SUNXI_MUSB_VEND0_PIO_MODE, musb->mregs + SUNXI_MUSB_VEND0);
 
        /* Register notifier before calling phy_init() */
-       if (musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE) {
-               ret = extcon_register_notifier(glue->extcon, EXTCON_USB_HOST,
-                                              &glue->host_nb);
-               if (ret)
-                       goto error_reset_assert;
-       }
+       ret = extcon_register_notifier(glue->extcon, EXTCON_USB_HOST,
+                                      &glue->host_nb);
+       if (ret)
+               goto error_reset_assert;
 
        ret = phy_init(glue->phy);
        if (ret)
        return 0;
 
 error_unregister_notifier:
-       if (musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
-               extcon_unregister_notifier(glue->extcon, EXTCON_USB_HOST,
-                                          &glue->host_nb);
+       extcon_unregister_notifier(glue->extcon, EXTCON_USB_HOST,
+                                  &glue->host_nb);
 error_reset_assert:
        if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags))
                reset_control_assert(glue->rst);
 
        phy_exit(glue->phy);
 
-       if (musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
-               extcon_unregister_notifier(glue->extcon, EXTCON_USB_HOST,
-                                          &glue->host_nb);
+       extcon_unregister_notifier(glue->extcon, EXTCON_USB_HOST,
+                                  &glue->host_nb);
 
        if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags))
                reset_control_assert(glue->rst);
        return 0;
 }
 
-static int sunxi_set_mode(struct musb *musb, u8 mode)
-{
-       struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
-       int ret;
-
-       if (mode == MUSB_HOST) {
-               ret = phy_power_on(glue->phy);
-               if (ret)
-                       return ret;
-
-               set_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
-               /* Stop musb work from turning vbus off again */
-               set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
-               musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
-       }
-
-       return 0;
-}
-
 static void sunxi_musb_enable(struct musb *musb)
 {
        struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
        .exit           = sunxi_musb_exit,
        .enable         = sunxi_musb_enable,
        .disable        = sunxi_musb_disable,
-       .set_mode       = sunxi_set_mode,
        .fifo_offset    = sunxi_musb_fifo_offset,
        .ep_offset      = sunxi_musb_ep_offset,
        .busctl_offset  = sunxi_musb_busctl_offset,
                return -EINVAL;
        }
 
-       glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
-       if (!glue)
-               return -ENOMEM;
-
        memset(&pdata, 0, sizeof(pdata));
        switch (usb_get_dr_mode(&pdev->dev)) {
 #if defined CONFIG_USB_MUSB_DUAL_ROLE || defined CONFIG_USB_MUSB_HOST
                pdata.mode = MUSB_PORT_MODE_HOST;
                break;
 #endif
+#if defined CONFIG_USB_MUSB_DUAL_ROLE || defined CONFIG_USB_MUSB_GADGET
+       case USB_DR_MODE_PERIPHERAL:
+               pdata.mode = MUSB_PORT_MODE_GADGET;
+               break;
+#endif
 #ifdef CONFIG_USB_MUSB_DUAL_ROLE
        case USB_DR_MODE_OTG:
-               glue->extcon = extcon_get_edev_by_phandle(&pdev->dev, 0);
-               if (IS_ERR(glue->extcon)) {
-                       if (PTR_ERR(glue->extcon) == -EPROBE_DEFER)
-                               return -EPROBE_DEFER;
-                       dev_err(&pdev->dev, "Invalid or missing extcon\n");
-                       return PTR_ERR(glue->extcon);
-               }
                pdata.mode = MUSB_PORT_MODE_DUAL_ROLE;
                break;
 #endif
        pdata.platform_ops      = &sunxi_musb_ops;
        pdata.config            = &sunxi_musb_hdrc_config;
 
+       glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
+       if (!glue)
+               return -ENOMEM;
+
        glue->dev = &pdev->dev;
        INIT_WORK(&glue->work, sunxi_musb_work);
        glue->host_nb.notifier_call = sunxi_musb_host_notifier;
                }
        }
 
+       glue->extcon = extcon_get_edev_by_phandle(&pdev->dev, 0);
+       if (IS_ERR(glue->extcon)) {
+               if (PTR_ERR(glue->extcon) == -EPROBE_DEFER)
+                       return -EPROBE_DEFER;
+               dev_err(&pdev->dev, "Invalid or missing extcon\n");
+               return PTR_ERR(glue->extcon);
+       }
+
        glue->phy = devm_phy_get(&pdev->dev, "usb");
        if (IS_ERR(glue->phy)) {
                if (PTR_ERR(glue->phy) == -EPROBE_DEFER)