]> Pileus Git - ~andy/linux/blobdiff - drivers/usb/phy/omap-usb2.c
Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso...
[~andy/linux] / drivers / usb / phy / omap-usb2.c
index 26ae8f49225c9b2803fe6624f1ec1bfa488d3018..844ab68f08d04d6600594fb74fc56a3225b079b2 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/err.h>
 #include <linux/pm_runtime.h>
 #include <linux/delay.h>
+#include <linux/usb/omap_control_usb.h>
 
 /**
  * omap_usb2_set_comparator - links the comparator present in the sytem with
@@ -52,29 +53,6 @@ int omap_usb2_set_comparator(struct phy_companion *comparator)
 }
 EXPORT_SYMBOL_GPL(omap_usb2_set_comparator);
 
-/**
- * omap_usb_phy_power - power on/off the phy using control module reg
- * @phy: struct omap_usb *
- * @on: 0 or 1, based on powering on or off the PHY
- *
- * XXX: Remove this function once control module driver gets merged
- */
-static void omap_usb_phy_power(struct omap_usb *phy, int on)
-{
-       u32 val;
-
-       if (on) {
-               val = readl(phy->control_dev);
-               if (val & PHY_PD) {
-                       writel(~PHY_PD, phy->control_dev);
-                       /* XXX: add proper documentation for this delay */
-                       mdelay(200);
-               }
-       } else {
-               writel(PHY_PD, phy->control_dev);
-       }
-}
-
 static int omap_usb_set_vbus(struct usb_otg *otg, bool enabled)
 {
        struct omap_usb *phy = phy_to_omapusb(otg->phy);
@@ -124,7 +102,7 @@ static int omap_usb2_suspend(struct usb_phy *x, int suspend)
        struct omap_usb *phy = phy_to_omapusb(x);
 
        if (suspend && !phy->is_suspended) {
-               omap_usb_phy_power(phy, 0);
+               omap_control_usb_phy_power(phy->control_dev, 0);
                pm_runtime_put_sync(phy->dev);
                phy->is_suspended = 1;
        } else if (!suspend && phy->is_suspended) {
@@ -134,7 +112,7 @@ static int omap_usb2_suspend(struct usb_phy *x, int suspend)
                                                                        ret);
                        return ret;
                }
-               omap_usb_phy_power(phy, 1);
+               omap_control_usb_phy_power(phy->control_dev, 1);
                phy->is_suspended = 0;
        }
 
@@ -145,7 +123,6 @@ static int omap_usb2_probe(struct platform_device *pdev)
 {
        struct omap_usb                 *phy;
        struct usb_otg                  *otg;
-       struct resource                 *res;
 
        phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
        if (!phy) {
@@ -165,17 +142,16 @@ static int omap_usb2_probe(struct platform_device *pdev)
        phy->phy.label          = "omap-usb2";
        phy->phy.set_suspend    = omap_usb2_suspend;
        phy->phy.otg            = otg;
+       phy->phy.type           = USB_PHY_TYPE_USB2;
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-
-       phy->control_dev = devm_request_and_ioremap(&pdev->dev, res);
-       if (phy->control_dev == NULL) {
-               dev_err(&pdev->dev, "Failed to obtain io memory\n");
-               return -ENXIO;
+       phy->control_dev = omap_get_control_dev();
+       if (IS_ERR(phy->control_dev)) {
+               dev_dbg(&pdev->dev, "Failed to get control device\n");
+               return -ENODEV;
        }
 
        phy->is_suspended       = 1;
-       omap_usb_phy_power(phy, 0);
+       omap_control_usb_phy_power(phy->control_dev, 0);
 
        otg->set_host           = omap_usb_set_host;
        otg->set_peripheral     = omap_usb_set_peripheral;
@@ -190,7 +166,13 @@ static int omap_usb2_probe(struct platform_device *pdev)
        }
        clk_prepare(phy->wkupclk);
 
-       usb_add_phy(&phy->phy, USB_PHY_TYPE_USB2);
+       phy->optclk = devm_clk_get(phy->dev, "usb_otg_ss_refclk960m");
+       if (IS_ERR(phy->optclk))
+               dev_vdbg(&pdev->dev, "unable to get refclk960m\n");
+       else
+               clk_prepare(phy->optclk);
+
+       usb_add_phy_dev(&phy->phy);
 
        platform_set_drvdata(pdev, phy);
 
@@ -204,6 +186,8 @@ static int omap_usb2_remove(struct platform_device *pdev)
        struct omap_usb *phy = platform_get_drvdata(pdev);
 
        clk_unprepare(phy->wkupclk);
+       if (!IS_ERR(phy->optclk))
+               clk_unprepare(phy->optclk);
        usb_remove_phy(&phy->phy);
 
        return 0;
@@ -217,6 +201,8 @@ static int omap_usb2_runtime_suspend(struct device *dev)
        struct omap_usb *phy = platform_get_drvdata(pdev);
 
        clk_disable(phy->wkupclk);
+       if (!IS_ERR(phy->optclk))
+               clk_disable(phy->optclk);
 
        return 0;
 }
@@ -228,9 +214,25 @@ static int omap_usb2_runtime_resume(struct device *dev)
        struct omap_usb *phy = platform_get_drvdata(pdev);
 
        ret = clk_enable(phy->wkupclk);
-       if (ret < 0)
+       if (ret < 0) {
                dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret);
+               goto err0;
+       }
+
+       if (!IS_ERR(phy->optclk)) {
+               ret = clk_enable(phy->optclk);
+               if (ret < 0) {
+                       dev_err(phy->dev, "Failed to enable optclk %d\n", ret);
+                       goto err1;
+               }
+       }
+
+       return 0;
+
+err1:
+       clk_disable(phy->wkupclk);
 
+err0:
        return ret;
 }