Merge tag 'xceiv-for-v3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi...
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 25 Jan 2013 17:09:46 +0000 (09:09 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 25 Jan 2013 17:09:46 +0000 (09:09 -0800)
Felipe writes:
usb: xceiv: patches for v3.9 merge window

Two new PHY drivers coming here: one for Samsung,
one for OMAP. Both architectures are adding USB3
support to mainline kernel.

The PHY layer now allows us to have mulitple PHYs
of the same type, which is necessary for platforms
which provide more than one USB peripheral port.

There's also a few cleanups here: removal of __dev*
annotations, conversion of a cast to to_delayed_work(),
and mxs-phy learns about ->set_suspend.

1  2 
drivers/usb/dwc3/core.c
drivers/usb/gadget/s3c-hsotg.c
drivers/usb/host/ehci-s5p.c
drivers/usb/host/ohci-exynos.c
drivers/usb/musb/omap2430.c
drivers/usb/otg/mv_otg.c

diff --combined drivers/usb/dwc3/core.c
index 177f4c61acab915ec2dc412b8fd4192c89ea0702,804402510dea925c4ba062503a87e806b07feef4..999909451e37ef75e9fb49d42f35fc34bceb646f
@@@ -420,21 -420,24 +420,27 @@@ static int dwc3_probe(struct platform_d
                return -ENOMEM;
        }
  
-       dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
+       if (node) {
+               dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
+               dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
+       } else {
+               dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
+               dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
+       }
        if (IS_ERR_OR_NULL(dwc->usb2_phy)) {
                dev_err(dev, "no usb2 phy configured\n");
                return -EPROBE_DEFER;
        }
  
-       dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
        if (IS_ERR_OR_NULL(dwc->usb3_phy)) {
                dev_err(dev, "no usb3 phy configured\n");
                return -EPROBE_DEFER;
        }
  
 +      usb_phy_set_suspend(dwc->usb2_phy, 0);
 +      usb_phy_set_suspend(dwc->usb3_phy, 0);
 +
        spin_lock_init(&dwc->lock);
        platform_set_drvdata(pdev, dwc);
  
        else
                dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
  
-       if (of_get_property(node, "tx-fifo-resize", NULL))
-               dwc->needs_fifo_resize = true;
+       dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
  
        pm_runtime_enable(dev);
        pm_runtime_get_sync(dev);
@@@ -553,9 -555,9 +558,9 @@@ err0
  static int dwc3_remove(struct platform_device *pdev)
  {
        struct dwc3     *dwc = platform_get_drvdata(pdev);
 -      struct resource *res;
  
 -      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 +      usb_phy_set_suspend(dwc->usb2_phy, 1);
 +      usb_phy_set_suspend(dwc->usb3_phy, 1);
  
        pm_runtime_put(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
        return 0;
  }
  
+ #ifdef CONFIG_OF
+ static const struct of_device_id of_dwc3_match[] = {
+       {
+               .compatible = "synopsys,dwc3"
+       },
+       { },
+ };
+ MODULE_DEVICE_TABLE(of, of_dwc3_match);
+ #endif
  static struct platform_driver dwc3_driver = {
        .probe          = dwc3_probe,
        .remove         = dwc3_remove,
        .driver         = {
                .name   = "dwc3",
+               .of_match_table = of_match_ptr(of_dwc3_match),
        },
  };
  
index e1cd0f1adfb9d9509bc1c306e11e1285d219d083,2143df358072a0cdfc0a4f8f9328d31bef9d717e..e97df1d094dd6be599cd4adb72ab522e380bce30
@@@ -32,6 -32,7 +32,7 @@@
  
  #include <linux/usb/ch9.h>
  #include <linux/usb/gadget.h>
+ #include <linux/usb/phy.h>
  #include <linux/platform_data/s3c-hsotg.h>
  
  #include <mach/map.h>
@@@ -133,7 -134,9 +134,9 @@@ struct s3c_hsotg_ep 
   * struct s3c_hsotg - driver state.
   * @dev: The parent device supplied to the probe function
   * @driver: USB gadget driver
-  * @plat: The platform specific configuration data.
+  * @phy: The otg phy transceiver structure for phy control.
+  * @plat: The platform specific configuration data. This can be removed once
+  * all SoCs support usb transceiver.
   * @regs: The memory area mapped for accessing registers.
   * @irq: The IRQ number we are using
   * @supplies: Definition of USB power supplies
  struct s3c_hsotg {
        struct device            *dev;
        struct usb_gadget_driver *driver;
+       struct usb_phy          *phy;
        struct s3c_hsotg_plat    *plat;
  
        spinlock_t              lock;
@@@ -2854,7 -2858,10 +2858,10 @@@ static void s3c_hsotg_phy_enable(struc
        struct platform_device *pdev = to_platform_device(hsotg->dev);
  
        dev_dbg(hsotg->dev, "pdev 0x%p\n", pdev);
-       if (hsotg->plat->phy_init)
+       if (hsotg->phy)
+               usb_phy_init(hsotg->phy);
+       else if (hsotg->plat->phy_init)
                hsotg->plat->phy_init(pdev, hsotg->plat->phy_type);
  }
  
@@@ -2869,7 -2876,9 +2876,9 @@@ static void s3c_hsotg_phy_disable(struc
  {
        struct platform_device *pdev = to_platform_device(hsotg->dev);
  
-       if (hsotg->plat->phy_exit)
+       if (hsotg->phy)
+               usb_phy_shutdown(hsotg->phy);
+       else if (hsotg->plat->phy_exit)
                hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type);
  }
  
@@@ -3055,7 -3064,7 +3064,7 @@@ static int s3c_hsotg_pullup(struct usb_
        return 0;
  }
  
 -static struct usb_gadget_ops s3c_hsotg_gadget_ops = {
 +static const struct usb_gadget_ops s3c_hsotg_gadget_ops = {
        .get_frame      = s3c_hsotg_gadget_getframe,
        .udc_start              = s3c_hsotg_udc_start,
        .udc_stop               = s3c_hsotg_udc_stop,
@@@ -3477,11 -3486,12 +3486,11 @@@ static void s3c_hsotg_delete_debug(stru
  /**
   * s3c_hsotg_release - release callback for hsotg device
   * @dev: Device to for which release is called
 + *
 + * Nothing to do as the resource is allocated using devm_ API.
   */
  static void s3c_hsotg_release(struct device *dev)
  {
 -      struct s3c_hsotg *hsotg = dev_get_drvdata(dev);
 -
 -      kfree(hsotg);
  }
  
  /**
  static int s3c_hsotg_probe(struct platform_device *pdev)
  {
        struct s3c_hsotg_plat *plat = pdev->dev.platform_data;
+       struct usb_phy *phy;
        struct device *dev = &pdev->dev;
        struct s3c_hsotg_ep *eps;
        struct s3c_hsotg *hsotg;
        int ret;
        int i;
  
-       plat = pdev->dev.platform_data;
-       if (!plat) {
-               dev_err(&pdev->dev, "no platform data defined\n");
-               return -EINVAL;
-       }
        hsotg = devm_kzalloc(&pdev->dev, sizeof(struct s3c_hsotg), GFP_KERNEL);
        if (!hsotg) {
                dev_err(dev, "cannot get memory\n");
                return -ENOMEM;
        }
  
+       phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
+       if (IS_ERR_OR_NULL(phy)) {
+               /* Fallback for pdata */
+               plat = pdev->dev.platform_data;
+               if (!plat) {
+                       dev_err(&pdev->dev, "no platform data or transceiver defined\n");
+                       return -EPROBE_DEFER;
+               } else {
+                       hsotg->plat = plat;
+               }
+       } else {
+               hsotg->phy = phy;
+       }
        hsotg->dev = dev;
-       hsotg->plat = plat;
  
        hsotg->clk = devm_clk_get(&pdev->dev, "otg");
        if (IS_ERR(hsotg->clk)) {
        for (i = 0; i < ARRAY_SIZE(hsotg->supplies); i++)
                hsotg->supplies[i].supply = s3c_hsotg_supply_names[i];
  
 -      ret = regulator_bulk_get(dev, ARRAY_SIZE(hsotg->supplies),
 +      ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(hsotg->supplies),
                                 hsotg->supplies);
        if (ret) {
                dev_err(dev, "failed to request supplies: %d\n", ret);
@@@ -3662,6 -3680,8 +3679,6 @@@ err_ep_mem
        kfree(eps);
  err_supplies:
        s3c_hsotg_phy_disable(hsotg);
 -      regulator_bulk_free(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
 -
  err_clk:
        clk_disable_unprepare(hsotg->clk);
  
@@@ -3686,6 -3706,7 +3703,6 @@@ static int s3c_hsotg_remove(struct plat
        }
  
        s3c_hsotg_phy_disable(hsotg);
 -      regulator_bulk_free(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
  
        clk_disable_unprepare(hsotg->clk);
  
index f18e6ac081aa7ac88c0ab9e7531b1d051dc08ce0,d603e6ec19a56cd47b522048cd35b2f934c14beb..20ebf6a8b7f4736c9cd448a9653de41b9d88c48a
@@@ -17,6 -17,8 +17,8 @@@
  #include <linux/platform_device.h>
  #include <linux/of_gpio.h>
  #include <linux/platform_data/usb-ehci-s5p.h>
+ #include <linux/usb/phy.h>
+ #include <linux/usb/samsung_usb_phy.h>
  #include <plat/usb-phy.h>
  
  #define EHCI_INSNREG00(base)                  (base + 0x90)
@@@ -32,6 -34,9 +34,9 @@@ struct s5p_ehci_hcd 
        struct device *dev;
        struct usb_hcd *hcd;
        struct clk *clk;
+       struct usb_phy *phy;
+       struct usb_otg *otg;
+       struct s5p_ehci_platdata *pdata;
  };
  
  static const struct hc_driver s5p_ehci_hc_driver = {
        .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
  };
  
+ static void s5p_ehci_phy_enable(struct s5p_ehci_hcd *s5p_ehci)
+ {
+       struct platform_device *pdev = to_platform_device(s5p_ehci->dev);
+       if (s5p_ehci->phy)
+               usb_phy_init(s5p_ehci->phy);
+       else if (s5p_ehci->pdata->phy_init)
+               s5p_ehci->pdata->phy_init(pdev, USB_PHY_TYPE_HOST);
+ }
+ static void s5p_ehci_phy_disable(struct s5p_ehci_hcd *s5p_ehci)
+ {
+       struct platform_device *pdev = to_platform_device(s5p_ehci->dev);
+       if (s5p_ehci->phy)
+               usb_phy_shutdown(s5p_ehci->phy);
+       else if (s5p_ehci->pdata->phy_exit)
+               s5p_ehci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST);
+ }
  static void s5p_setup_vbus_gpio(struct platform_device *pdev)
  {
        int err;
@@@ -87,20 -112,15 +112,15 @@@ static u64 ehci_s5p_dma_mask = DMA_BIT_
  
  static int s5p_ehci_probe(struct platform_device *pdev)
  {
-       struct s5p_ehci_platdata *pdata;
+       struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
        struct s5p_ehci_hcd *s5p_ehci;
        struct usb_hcd *hcd;
        struct ehci_hcd *ehci;
        struct resource *res;
+       struct usb_phy *phy;
        int irq;
        int err;
  
-       pdata = pdev->dev.platform_data;
-       if (!pdata) {
-               dev_err(&pdev->dev, "No platform data defined\n");
-               return -EINVAL;
-       }
        /*
         * Right now device-tree probed devices don't get dma_mask set.
         * Since shared usb code relies on it, set it here for now.
        if (!s5p_ehci)
                return -ENOMEM;
  
+       phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
+       if (IS_ERR_OR_NULL(phy)) {
+               /* Fallback to pdata */
+               if (!pdata) {
+                       dev_warn(&pdev->dev, "no platform data or transceiver defined\n");
+                       return -EPROBE_DEFER;
+               } else {
+                       s5p_ehci->pdata = pdata;
+               }
+       } else {
+               s5p_ehci->phy = phy;
+               s5p_ehci->otg = phy->otg;
+       }
        s5p_ehci->dev = &pdev->dev;
  
        hcd = usb_create_hcd(&s5p_ehci_hc_driver, &pdev->dev,
                goto fail_io;
        }
  
-       if (pdata->phy_init)
-               pdata->phy_init(pdev, S5P_USB_PHY_HOST);
+       if (s5p_ehci->otg)
+               s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self);
+       s5p_ehci_phy_enable(s5p_ehci);
  
        ehci = hcd_to_ehci(hcd);
        ehci->caps = hcd->regs;
        err = usb_add_hcd(hcd, irq, IRQF_SHARED);
        if (err) {
                dev_err(&pdev->dev, "Failed to add USB HCD\n");
-               goto fail_io;
+               goto fail_add_hcd;
        }
  
        platform_set_drvdata(pdev, s5p_ehci);
  
        return 0;
  
+ fail_add_hcd:
+       s5p_ehci_phy_disable(s5p_ehci);
  fail_io:
        clk_disable_unprepare(s5p_ehci->clk);
  fail_clk:
  
  static int s5p_ehci_remove(struct platform_device *pdev)
  {
-       struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
        struct s5p_ehci_hcd *s5p_ehci = platform_get_drvdata(pdev);
        struct usb_hcd *hcd = s5p_ehci->hcd;
  
        usb_remove_hcd(hcd);
  
-       if (pdata && pdata->phy_exit)
-               pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
+       if (s5p_ehci->otg)
+               s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self);
+       s5p_ehci_phy_disable(s5p_ehci);
  
        clk_disable_unprepare(s5p_ehci->clk);
  
@@@ -222,14 -261,14 +261,14 @@@ static int s5p_ehci_suspend(struct devi
        struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev);
        struct usb_hcd *hcd = s5p_ehci->hcd;
        bool do_wakeup = device_may_wakeup(dev);
-       struct platform_device *pdev = to_platform_device(dev);
-       struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
        int rc;
  
        rc = ehci_suspend(hcd, do_wakeup);
  
-       if (pdata && pdata->phy_exit)
-               pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
+       if (s5p_ehci->otg)
+               s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self);
+       s5p_ehci_phy_disable(s5p_ehci);
  
        clk_disable_unprepare(s5p_ehci->clk);
  
@@@ -240,13 -279,13 +279,13 @@@ static int s5p_ehci_resume(struct devic
  {
        struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev);
        struct usb_hcd *hcd = s5p_ehci->hcd;
-       struct platform_device *pdev = to_platform_device(dev);
-       struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
  
        clk_prepare_enable(s5p_ehci->clk);
  
-       if (pdata && pdata->phy_init)
-               pdata->phy_init(pdev, S5P_USB_PHY_HOST);
+       if (s5p_ehci->otg)
+               s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self);
+       s5p_ehci_phy_enable(s5p_ehci);
  
        /* DMA burst Enable */
        writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs));
@@@ -266,7 -305,7 +305,7 @@@ static const struct dev_pm_ops s5p_ehci
  
  #ifdef CONFIG_OF
  static const struct of_device_id exynos_ehci_match[] = {
 -      { .compatible = "samsung,exynos-ehci" },
 +      { .compatible = "samsung,exynos4210-ehci" },
        {},
  };
  MODULE_DEVICE_TABLE(of, exynos_ehci_match);
index 77f2017c33c42229c026e1f07d4335a183d76548,1b3840980177ef1098809b22ade3243a7820c552..e3b7e85120e44480ead256132098f7c7d3418710
  #include <linux/of.h>
  #include <linux/platform_device.h>
  #include <linux/platform_data/usb-exynos.h>
+ #include <linux/usb/phy.h>
+ #include <linux/usb/samsung_usb_phy.h>
  #include <plat/usb-phy.h>
  
  struct exynos_ohci_hcd {
        struct device *dev;
        struct usb_hcd *hcd;
        struct clk *clk;
+       struct usb_phy *phy;
+       struct usb_otg *otg;
+       struct exynos4_ohci_platdata *pdata;
  };
  
+ static void exynos_ohci_phy_enable(struct exynos_ohci_hcd *exynos_ohci)
+ {
+       struct platform_device *pdev = to_platform_device(exynos_ohci->dev);
+       if (exynos_ohci->phy)
+               usb_phy_init(exynos_ohci->phy);
+       else if (exynos_ohci->pdata->phy_init)
+               exynos_ohci->pdata->phy_init(pdev, USB_PHY_TYPE_HOST);
+ }
+ static void exynos_ohci_phy_disable(struct exynos_ohci_hcd *exynos_ohci)
+ {
+       struct platform_device *pdev = to_platform_device(exynos_ohci->dev);
+       if (exynos_ohci->phy)
+               usb_phy_shutdown(exynos_ohci->phy);
+       else if (exynos_ohci->pdata->phy_exit)
+               exynos_ohci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST);
+ }
  static int ohci_exynos_reset(struct usb_hcd *hcd)
  {
        return ohci_init(hcd_to_ohci(hcd));
@@@ -78,20 -103,15 +103,15 @@@ static u64 ohci_exynos_dma_mask = DMA_B
  
  static int exynos_ohci_probe(struct platform_device *pdev)
  {
-       struct exynos4_ohci_platdata *pdata;
+       struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data;
        struct exynos_ohci_hcd *exynos_ohci;
        struct usb_hcd *hcd;
        struct ohci_hcd *ohci;
        struct resource *res;
+       struct usb_phy *phy;
        int irq;
        int err;
  
-       pdata = pdev->dev.platform_data;
-       if (!pdata) {
-               dev_err(&pdev->dev, "No platform data defined\n");
-               return -EINVAL;
-       }
        /*
         * Right now device-tree probed devices don't get dma_mask set.
         * Since shared usb code relies on it, set it here for now.
        if (!exynos_ohci)
                return -ENOMEM;
  
+       phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
+       if (IS_ERR_OR_NULL(phy)) {
+               /* Fallback to pdata */
+               if (!pdata) {
+                       dev_warn(&pdev->dev, "no platform data or transceiver defined\n");
+                       return -EPROBE_DEFER;
+               } else {
+                       exynos_ohci->pdata = pdata;
+               }
+       } else {
+               exynos_ohci->phy = phy;
+               exynos_ohci->otg = phy->otg;
+       }
        exynos_ohci->dev = &pdev->dev;
  
        hcd = usb_create_hcd(&exynos_ohci_hc_driver, &pdev->dev,
                goto fail_io;
        }
  
-       if (pdata->phy_init)
-               pdata->phy_init(pdev, S5P_USB_PHY_HOST);
+       if (exynos_ohci->otg)
+               exynos_ohci->otg->set_host(exynos_ohci->otg,
+                                       &exynos_ohci->hcd->self);
+       exynos_ohci_phy_enable(exynos_ohci);
  
        ohci = hcd_to_ohci(hcd);
        ohci_hcd_init(ohci);
        err = usb_add_hcd(hcd, irq, IRQF_SHARED);
        if (err) {
                dev_err(&pdev->dev, "Failed to add USB HCD\n");
-               goto fail_io;
+               goto fail_add_hcd;
        }
  
        platform_set_drvdata(pdev, exynos_ohci);
  
        return 0;
  
+ fail_add_hcd:
+       exynos_ohci_phy_disable(exynos_ohci);
  fail_io:
        clk_disable_unprepare(exynos_ohci->clk);
  fail_clk:
  
  static int exynos_ohci_remove(struct platform_device *pdev)
  {
-       struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data;
        struct exynos_ohci_hcd *exynos_ohci = platform_get_drvdata(pdev);
        struct usb_hcd *hcd = exynos_ohci->hcd;
  
        usb_remove_hcd(hcd);
  
-       if (pdata && pdata->phy_exit)
-               pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
+       if (exynos_ohci->otg)
+               exynos_ohci->otg->set_host(exynos_ohci->otg,
+                                       &exynos_ohci->hcd->self);
+       exynos_ohci_phy_disable(exynos_ohci);
  
        clk_disable_unprepare(exynos_ohci->clk);
  
@@@ -208,8 -249,6 +249,6 @@@ static int exynos_ohci_suspend(struct d
        struct exynos_ohci_hcd *exynos_ohci = dev_get_drvdata(dev);
        struct usb_hcd *hcd = exynos_ohci->hcd;
        struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-       struct platform_device *pdev = to_platform_device(dev);
-       struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data;
        unsigned long flags;
        int rc = 0;
  
  
        clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
  
-       if (pdata && pdata->phy_exit)
-               pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
+       if (exynos_ohci->otg)
+               exynos_ohci->otg->set_host(exynos_ohci->otg,
+                                       &exynos_ohci->hcd->self);
+       exynos_ohci_phy_disable(exynos_ohci);
  
        clk_disable_unprepare(exynos_ohci->clk);
  
@@@ -243,13 -285,14 +285,14 @@@ static int exynos_ohci_resume(struct de
  {
        struct exynos_ohci_hcd *exynos_ohci = dev_get_drvdata(dev);
        struct usb_hcd *hcd = exynos_ohci->hcd;
-       struct platform_device *pdev = to_platform_device(dev);
-       struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data;
  
        clk_prepare_enable(exynos_ohci->clk);
  
-       if (pdata && pdata->phy_init)
-               pdata->phy_init(pdev, S5P_USB_PHY_HOST);
+       if (exynos_ohci->otg)
+               exynos_ohci->otg->set_host(exynos_ohci->otg,
+                                       &exynos_ohci->hcd->self);
+       exynos_ohci_phy_enable(exynos_ohci);
  
        ohci_resume(hcd, false);
  
@@@ -267,7 -310,7 +310,7 @@@ static const struct dev_pm_ops exynos_o
  
  #ifdef CONFIG_OF
  static const struct of_device_id exynos_ohci_match[] = {
 -      { .compatible = "samsung,exynos-ohci" },
 +      { .compatible = "samsung,exynos4210-ohci" },
        {},
  };
  MODULE_DEVICE_TABLE(of, exynos_ohci_match);
index bb48796e5213ae14805484223d865f04fb7c6e39,d100360eab7a294c5ebdcc4abd813651f67f9c55..1762354fe793198fbfc075fb95ab22468dc34a8b
@@@ -37,6 -37,7 +37,7 @@@
  #include <linux/err.h>
  #include <linux/delay.h>
  #include <linux/usb/musb-omap.h>
+ #include <linux/usb/omap_control_usb.h>
  
  #include "musb_core.h"
  #include "omap2430.h"
@@@ -46,7 -47,7 +47,7 @@@ struct omap2430_glue 
        struct platform_device  *musb;
        enum omap_musb_vbus_id_status status;
        struct work_struct      omap_musb_mailbox_work;
-       u32 __iomem             *control_otghs;
+       struct device           *control_otghs;
  };
  #define glue_to_musb(g)               platform_get_drvdata(g->musb)
  
@@@ -54,26 -55,6 +55,6 @@@ struct omap2430_glue         *_glue
  
  static struct timer_list musb_idle_timer;
  
- /**
-  * omap4_usb_phy_mailbox - write to usb otg mailbox
-  * @glue: struct omap2430_glue *
-  * @val: the value to be written to the mailbox
-  *
-  * On detection of a device (ID pin is grounded), this API should be called
-  * to set AVALID, VBUSVALID and ID pin is grounded.
-  *
-  * When OMAP is connected to a host (OMAP in device mode), this API
-  * is called to set AVALID, VBUSVALID and ID pin in high impedance.
-  *
-  * XXX: This function will be removed once we have a seperate driver for
-  * control module
-  */
- static void omap4_usb_phy_mailbox(struct omap2430_glue *glue, u32 val)
- {
-       if (glue->control_otghs)
-               writel(val, glue->control_otghs);
- }
  static void musb_do_idle(unsigned long _musb)
  {
        struct musb     *musb = (void *)_musb;
@@@ -255,11 -236,11 +236,11 @@@ static inline void omap2430_low_level_i
  void omap_musb_mailbox(enum omap_musb_vbus_id_status status)
  {
        struct omap2430_glue    *glue = _glue;
 -      struct musb             *musb = glue_to_musb(glue);
  
 -      glue->status = status;
 -      if (!musb) {
 -              dev_err(glue->dev, "musb core is not yet ready\n");
 +      if (glue && glue_to_musb(glue)) {
 +              glue->status = status;
 +      } else {
 +              pr_err("%s: musb core is not yet ready\n", __func__);
                return;
        }
  
@@@ -269,7 -250,6 +250,6 @@@ EXPORT_SYMBOL_GPL(omap_musb_mailbox)
  
  static void omap_musb_set_mailbox(struct omap2430_glue *glue)
  {
-       u32 val;
        struct musb *musb = glue_to_musb(glue);
        struct device *dev = musb->controller;
        struct musb_hdrc_platform_data *pdata = dev->platform_data;
                musb->xceiv->last_event = USB_EVENT_ID;
                if (musb->gadget_driver) {
                        pm_runtime_get_sync(dev);
-                       val = AVALID | VBUSVALID;
-                       omap4_usb_phy_mailbox(glue, val);
+                       omap_control_usb_set_mode(glue->control_otghs,
+                               USB_MODE_HOST);
                        omap2430_musb_set_vbus(musb, 1);
                }
                break;
                musb->xceiv->last_event = USB_EVENT_VBUS;
                if (musb->gadget_driver)
                        pm_runtime_get_sync(dev);
-               val = IDDIG | AVALID | VBUSVALID;
-               omap4_usb_phy_mailbox(glue, val);
+               omap_control_usb_set_mode(glue->control_otghs, USB_MODE_DEVICE);
                break;
  
        case OMAP_MUSB_ID_FLOAT:
                        if (musb->xceiv->otg->set_vbus)
                                otg_set_vbus(musb->xceiv->otg, 0);
                }
-               val = SESSEND | IDDIG;
-               omap4_usb_phy_mailbox(glue, val);
+               omap_control_usb_set_mode(glue->control_otghs,
+                       USB_MODE_DISCONNECT);
                break;
        default:
                dev_dbg(dev, "ID float\n");
@@@ -366,10 -345,15 +345,15 @@@ static int omap2430_musb_init(struct mu
         * up through ULPI.  TWL4030-family PMICs include one,
         * which needs a driver, drivers aren't always needed.
         */
-       musb->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
+       if (dev->parent->of_node)
+               musb->xceiv = devm_usb_get_phy_by_phandle(dev->parent,
+                   "usb-phy", 0);
+       else
+               musb->xceiv = devm_usb_get_phy_dev(dev, 0);
        if (IS_ERR_OR_NULL(musb->xceiv)) {
                pr_err("HS USB OTG: no transceiver configured\n");
 -              return -ENODEV;
 +              return -EPROBE_DEFER;
        }
  
        musb->isr = omap2430_musb_interrupt;
@@@ -415,7 -399,6 +399,6 @@@ err1
  static void omap2430_musb_enable(struct musb *musb)
  {
        u8              devctl;
-       u32             val;
        unsigned long timeout = jiffies + msecs_to_jiffies(1000);
        struct device *dev = musb->controller;
        struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
        switch (glue->status) {
  
        case OMAP_MUSB_ID_GROUND:
-               val = AVALID | VBUSVALID;
-               omap4_usb_phy_mailbox(glue, val);
+               omap_control_usb_set_mode(glue->control_otghs, USB_MODE_HOST);
                if (data->interface_type != MUSB_INTERFACE_UTMI)
                        break;
                devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
                break;
  
        case OMAP_MUSB_VBUS_VALID:
-               val = IDDIG | AVALID | VBUSVALID;
-               omap4_usb_phy_mailbox(glue, val);
+               omap_control_usb_set_mode(glue->control_otghs, USB_MODE_DEVICE);
                break;
  
        default:
  
  static void omap2430_musb_disable(struct musb *musb)
  {
-       u32 val;
        struct device *dev = musb->controller;
        struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
  
-       if (glue->status != OMAP_MUSB_UNKNOWN) {
-               val = SESSEND | IDDIG;
-               omap4_usb_phy_mailbox(glue, val);
-       }
+       if (glue->status != OMAP_MUSB_UNKNOWN)
+               omap_control_usb_set_mode(glue->control_otghs,
+                       USB_MODE_DISCONNECT);
  }
  
  static int omap2430_musb_exit(struct musb *musb)
@@@ -498,7 -477,6 +477,6 @@@ static int omap2430_probe(struct platfo
        struct omap2430_glue            *glue;
        struct device_node              *np = pdev->dev.of_node;
        struct musb_hdrc_config         *config;
-       struct resource                 *res;
        int                             ret = -ENOMEM;
  
        glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
        glue->musb                      = musb;
        glue->status                    = OMAP_MUSB_UNKNOWN;
  
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       glue->control_otghs = devm_request_and_ioremap(&pdev->dev, res);
-       if (glue->control_otghs == NULL)
-               dev_dbg(&pdev->dev, "Failed to obtain control memory\n");
        if (np) {
                pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
                if (!pdata) {
                        dev_err(&pdev->dev,
                                "failed to allocate musb platfrom data\n");
 -                      ret = -ENOMEM;
                        goto err2;
                }
  
                data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
                if (!data) {
                        dev_err(&pdev->dev,
 -                                      "failed to allocate musb board data\n");
 -                      ret = -ENOMEM;
 +                              "failed to allocate musb board data\n");
                        goto err2;
                }
  
                config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);
 -              if (!data) {
 +              if (!config) {
                        dev_err(&pdev->dev,
                                "failed to allocate musb hdrc config\n");
                        goto err2;
                of_property_read_u32(np, "ram_bits", (u32 *)&config->ram_bits);
                of_property_read_u32(np, "power", (u32 *)&pdata->power);
                config->multipoint = of_property_read_bool(np, "multipoint");
+               pdata->has_mailbox = of_property_read_bool(np,
+                   "ti,has-mailbox");
  
                pdata->board_data       = data;
                pdata->config           = config;
        }
  
+       if (pdata->has_mailbox) {
+               glue->control_otghs = omap_get_control_dev();
+               if (IS_ERR(glue->control_otghs)) {
+                       dev_vdbg(&pdev->dev, "Failed to get control device\n");
+                       return -ENODEV;
+               }
+       } else {
+               glue->control_otghs = ERR_PTR(-ENODEV);
+       }
        pdata->platform_ops             = &omap2430_ops;
  
        platform_set_drvdata(pdev, glue);
diff --combined drivers/usb/otg/mv_otg.c
index da2d60c06f152dcd87768e2054ee1c049b8427cf,5104bc2b67b34fffa9d444d75d8b5b4083fb8789..b6a9be31133b0dd15231c6b02ed05cbd10adade6
@@@ -240,7 -240,7 +240,7 @@@ static void otg_clock_enable(struct mv_
        unsigned int i;
  
        for (i = 0; i < mvotg->clknum; i++)
 -              clk_enable(mvotg->clk[i]);
 +              clk_prepare_enable(mvotg->clk[i]);
  }
  
  static void otg_clock_disable(struct mv_otg *mvotg)
        unsigned int i;
  
        for (i = 0; i < mvotg->clknum; i++)
 -              clk_disable(mvotg->clk[i]);
 +              clk_disable_unprepare(mvotg->clk[i]);
  }
  
  static int mv_otg_enable_internal(struct mv_otg *mvotg)
@@@ -420,7 -420,7 +420,7 @@@ static void mv_otg_work(struct work_str
        struct usb_otg *otg;
        int old_state;
  
-       mvotg = container_of((struct delayed_work *)work, struct mv_otg, work);
+       mvotg = container_of(to_delayed_work(work), struct mv_otg, work);
  
  run:
        /* work queue is single thread, or we need spin_lock to protect */
@@@ -662,9 -662,18 +662,9 @@@ static struct attribute_group inputs_at
  int mv_otg_remove(struct platform_device *pdev)
  {
        struct mv_otg *mvotg = platform_get_drvdata(pdev);
 -      int clk_i;
  
        sysfs_remove_group(&mvotg->pdev->dev.kobj, &inputs_attr_group);
  
 -      if (mvotg->irq)
 -              free_irq(mvotg->irq, mvotg);
 -
 -      if (mvotg->pdata->vbus)
 -              free_irq(mvotg->pdata->vbus->irq, mvotg);
 -      if (mvotg->pdata->id)
 -              free_irq(mvotg->pdata->id->irq, mvotg);
 -
        if (mvotg->qwork) {
                flush_workqueue(mvotg->qwork);
                destroy_workqueue(mvotg->qwork);
  
        mv_otg_disable(mvotg);
  
 -      if (mvotg->cap_regs)
 -              iounmap(mvotg->cap_regs);
 -
 -      if (mvotg->phy_regs)
 -              iounmap(mvotg->phy_regs);
 -
 -      for (clk_i = 0; clk_i <= mvotg->clknum; clk_i++)
 -              clk_put(mvotg->clk[clk_i]);
 -
        usb_remove_phy(&mvotg->phy);
        platform_set_drvdata(pdev, NULL);
  
 -      kfree(mvotg->phy.otg);
 -      kfree(mvotg);
 -
        return 0;
  }
  
@@@ -693,15 -714,17 +693,15 @@@ static int mv_otg_probe(struct platform
        }
  
        size = sizeof(*mvotg) + sizeof(struct clk *) * pdata->clknum;
 -      mvotg = kzalloc(size, GFP_KERNEL);
 +      mvotg = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
        if (!mvotg) {
                dev_err(&pdev->dev, "failed to allocate memory!\n");
                return -ENOMEM;
        }
  
 -      otg = kzalloc(sizeof *otg, GFP_KERNEL);
 -      if (!otg) {
 -              kfree(mvotg);
 +      otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
 +      if (!otg)
                return -ENOMEM;
 -      }
  
        platform_set_drvdata(pdev, mvotg);
  
  
        mvotg->clknum = pdata->clknum;
        for (clk_i = 0; clk_i < mvotg->clknum; clk_i++) {
 -              mvotg->clk[clk_i] = clk_get(&pdev->dev, pdata->clkname[clk_i]);
 +              mvotg->clk[clk_i] = devm_clk_get(&pdev->dev,
 +                                              pdata->clkname[clk_i]);
                if (IS_ERR(mvotg->clk[clk_i])) {
                        retval = PTR_ERR(mvotg->clk[clk_i]);
 -                      goto err_put_clk;
 +                      return retval;
                }
        }
  
        mvotg->qwork = create_singlethread_workqueue("mv_otg_queue");
        if (!mvotg->qwork) {
                dev_dbg(&pdev->dev, "cannot create workqueue for OTG\n");
 -              retval = -ENOMEM;
 -              goto err_put_clk;
 +              return -ENOMEM;
        }
  
        INIT_DELAYED_WORK(&mvotg->work, mv_otg_work);
                goto err_destroy_workqueue;
        }
  
 -      mvotg->phy_regs = ioremap(r->start, resource_size(r));
 +      mvotg->phy_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
        if (mvotg->phy_regs == NULL) {
                dev_err(&pdev->dev, "failed to map phy I/O memory\n");
                retval = -EFAULT;
        if (r == NULL) {
                dev_err(&pdev->dev, "no I/O memory resource defined\n");
                retval = -ENODEV;
 -              goto err_unmap_phyreg;
 +              goto err_destroy_workqueue;
        }
  
 -      mvotg->cap_regs = ioremap(r->start, resource_size(r));
 +      mvotg->cap_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
        if (mvotg->cap_regs == NULL) {
                dev_err(&pdev->dev, "failed to map I/O memory\n");
                retval = -EFAULT;
 -              goto err_unmap_phyreg;
 +              goto err_destroy_workqueue;
        }
  
        /* we will acces controller register, so enable the udc controller */
        retval = mv_otg_enable_internal(mvotg);
        if (retval) {
                dev_err(&pdev->dev, "mv otg enable error %d\n", retval);
 -              goto err_unmap_capreg;
 +              goto err_destroy_workqueue;
        }
  
        mvotg->op_regs =
                        + (readl(mvotg->cap_regs) & CAPLENGTH_MASK));
  
        if (pdata->id) {
 -              retval = request_threaded_irq(pdata->id->irq, NULL,
 -                                            mv_otg_inputs_irq,
 -                                            IRQF_ONESHOT, "id", mvotg);
 +              retval = devm_request_threaded_irq(&pdev->dev, pdata->id->irq,
 +                                              NULL, mv_otg_inputs_irq,
 +                                              IRQF_ONESHOT, "id", mvotg);
                if (retval) {
                        dev_info(&pdev->dev,
                                 "Failed to request irq for ID\n");
  
        if (pdata->vbus) {
                mvotg->clock_gating = 1;
 -              retval = request_threaded_irq(pdata->vbus->irq, NULL,
 -                                            mv_otg_inputs_irq,
 -                                            IRQF_ONESHOT, "vbus", mvotg);
 +              retval = devm_request_threaded_irq(&pdev->dev, pdata->vbus->irq,
 +                                              NULL, mv_otg_inputs_irq,
 +                                              IRQF_ONESHOT, "vbus", mvotg);
                if (retval) {
                        dev_info(&pdev->dev,
                                 "Failed to request irq for VBUS, "
        }
  
        mvotg->irq = r->start;
 -      if (request_irq(mvotg->irq, mv_otg_irq, IRQF_SHARED,
 +      if (devm_request_irq(&pdev->dev, mvotg->irq, mv_otg_irq, IRQF_SHARED,
                        driver_name, mvotg)) {
                dev_err(&pdev->dev, "Request irq %d for OTG failed\n",
                        mvotg->irq);
        if (retval < 0) {
                dev_err(&pdev->dev, "can't register transceiver, %d\n",
                        retval);
 -              goto err_free_irq;
 +              goto err_disable_clk;
        }
  
        retval = sysfs_create_group(&pdev->dev.kobj, &inputs_attr_group);
        if (retval < 0) {
                dev_dbg(&pdev->dev,
                        "Can't register sysfs attr group: %d\n", retval);
 -              goto err_set_transceiver;
 +              goto err_remove_phy;
        }
  
        spin_lock_init(&mvotg->wq_lock);
  
        return 0;
  
 -err_set_transceiver:
 +err_remove_phy:
        usb_remove_phy(&mvotg->phy);
 -err_free_irq:
 -      free_irq(mvotg->irq, mvotg);
  err_disable_clk:
 -      if (pdata->vbus)
 -              free_irq(pdata->vbus->irq, mvotg);
 -      if (pdata->id)
 -              free_irq(pdata->id->irq, mvotg);
        mv_otg_disable_internal(mvotg);
 -err_unmap_capreg:
 -      iounmap(mvotg->cap_regs);
 -err_unmap_phyreg:
 -      iounmap(mvotg->phy_regs);
  err_destroy_workqueue:
        flush_workqueue(mvotg->qwork);
        destroy_workqueue(mvotg->qwork);
 -err_put_clk:
 -      for (clk_i--; clk_i >= 0; clk_i--)
 -              clk_put(mvotg->clk[clk_i]);
  
        platform_set_drvdata(pdev, NULL);
 -      kfree(otg);
 -      kfree(mvotg);
  
        return retval;
  }