usb: phy: phy-generic: export init functions
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>
Tue, 30 Jul 2013 15:20:06 +0000 (17:20 +0200)
committerFelipe Balbi <balbi@ti.com>
Fri, 9 Aug 2013 14:34:02 +0000 (17:34 +0300)
This patch exports the mostly generic functions so they can be used from
other phy driver instead of duplicating the code.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
drivers/usb/phy/phy-generic.c
drivers/usb/phy/phy-generic.h [new file with mode: 0644]

index 406f8e43f852a4448a3fbd7e429bda32802c05e1..efe59f3f7fdae946f1d6b5c76b9e6f21a0143be1 100644 (file)
 #include <linux/regulator/consumer.h>
 #include <linux/of.h>
 
-struct usb_phy_gen_xceiv {
-       struct usb_phy phy;
-       struct device *dev;
-       struct clk *clk;
-       struct regulator *vcc;
-       struct regulator *reset;
-};
+#include "phy-generic.h"
 
 static struct platform_device *pd;
 
@@ -70,7 +64,7 @@ static int nop_set_suspend(struct usb_phy *x, int suspend)
        return 0;
 }
 
-static int nop_init(struct usb_phy *phy)
+int usb_gen_phy_init(struct usb_phy *phy)
 {
        struct usb_phy_gen_xceiv *nop = dev_get_drvdata(phy->dev);
 
@@ -90,8 +84,9 @@ static int nop_init(struct usb_phy *phy)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(usb_gen_phy_init);
 
-static void nop_shutdown(struct usb_phy *phy)
+void usb_gen_phy_shutdown(struct usb_phy *phy)
 {
        struct usb_phy_gen_xceiv *nop = dev_get_drvdata(phy->dev);
 
@@ -109,6 +104,7 @@ static void nop_shutdown(struct usb_phy *phy)
                        dev_err(phy->dev, "Failed to disable power\n");
        }
 }
+EXPORT_SYMBOL_GPL(usb_gen_phy_shutdown);
 
 static int nop_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget)
 {
@@ -139,53 +135,27 @@ static int nop_set_host(struct usb_otg *otg, struct usb_bus *host)
        return 0;
 }
 
-static int usb_phy_gen_xceiv_probe(struct platform_device *pdev)
+int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop,
+               enum usb_phy_type type, u32 clk_rate, bool needs_vcc,
+               bool needs_reset)
 {
-       struct device *dev = &pdev->dev;
-       struct usb_phy_gen_xceiv_platform_data *pdata =
-                       dev_get_platdata(&pdev->dev);
-       struct usb_phy_gen_xceiv        *nop;
-       enum usb_phy_type       type = USB_PHY_TYPE_USB2;
        int err;
-       u32 clk_rate = 0;
-       bool needs_vcc = false;
-       bool needs_reset = false;
 
-       nop = devm_kzalloc(&pdev->dev, sizeof(*nop), GFP_KERNEL);
-       if (!nop)
-               return -ENOMEM;
-
-       nop->phy.otg = devm_kzalloc(&pdev->dev, sizeof(*nop->phy.otg),
-                                                       GFP_KERNEL);
+       nop->phy.otg = devm_kzalloc(dev, sizeof(*nop->phy.otg),
+                       GFP_KERNEL);
        if (!nop->phy.otg)
                return -ENOMEM;
 
-       if (dev->of_node) {
-               struct device_node *node = dev->of_node;
-
-               if (of_property_read_u32(node, "clock-frequency", &clk_rate))
-                       clk_rate = 0;
-
-               needs_vcc = of_property_read_bool(node, "vcc-supply");
-               needs_reset = of_property_read_bool(node, "reset-supply");
-
-       } else if (pdata) {
-               type = pdata->type;
-               clk_rate = pdata->clk_rate;
-               needs_vcc = pdata->needs_vcc;
-               needs_reset = pdata->needs_reset;
-       }
-
-       nop->clk = devm_clk_get(&pdev->dev, "main_clk");
+       nop->clk = devm_clk_get(dev, "main_clk");
        if (IS_ERR(nop->clk)) {
-               dev_dbg(&pdev->dev, "Can't get phy clock: %ld\n",
+               dev_dbg(dev, "Can't get phy clock: %ld\n",
                                        PTR_ERR(nop->clk));
        }
 
        if (!IS_ERR(nop->clk) && clk_rate) {
                err = clk_set_rate(nop->clk, clk_rate);
                if (err) {
-                       dev_err(&pdev->dev, "Error setting clock rate\n");
+                       dev_err(dev, "Error setting clock rate\n");
                        return err;
                }
        }
@@ -193,33 +163,31 @@ static int usb_phy_gen_xceiv_probe(struct platform_device *pdev)
        if (!IS_ERR(nop->clk)) {
                err = clk_prepare(nop->clk);
                if (err) {
-                       dev_err(&pdev->dev, "Error preparing clock\n");
+                       dev_err(dev, "Error preparing clock\n");
                        return err;
                }
        }
 
-       nop->vcc = devm_regulator_get(&pdev->dev, "vcc");
+       nop->vcc = devm_regulator_get(dev, "vcc");
        if (IS_ERR(nop->vcc)) {
-               dev_dbg(&pdev->dev, "Error getting vcc regulator: %ld\n",
+               dev_dbg(dev, "Error getting vcc regulator: %ld\n",
                                        PTR_ERR(nop->vcc));
                if (needs_vcc)
                        return -EPROBE_DEFER;
        }
 
-       nop->reset = devm_regulator_get(&pdev->dev, "reset");
+       nop->reset = devm_regulator_get(dev, "reset");
        if (IS_ERR(nop->reset)) {
-               dev_dbg(&pdev->dev, "Error getting reset regulator: %ld\n",
+               dev_dbg(dev, "Error getting reset regulator: %ld\n",
                                        PTR_ERR(nop->reset));
                if (needs_reset)
                        return -EPROBE_DEFER;
        }
 
-       nop->dev                = &pdev->dev;
+       nop->dev                = dev;
        nop->phy.dev            = nop->dev;
        nop->phy.label          = "nop-xceiv";
        nop->phy.set_suspend    = nop_set_suspend;
-       nop->phy.init           = nop_init;
-       nop->phy.shutdown       = nop_shutdown;
        nop->phy.state          = OTG_STATE_UNDEFINED;
        nop->phy.type           = type;
 
@@ -227,6 +195,59 @@ static int usb_phy_gen_xceiv_probe(struct platform_device *pdev)
        nop->phy.otg->set_host          = nop_set_host;
        nop->phy.otg->set_peripheral    = nop_set_peripheral;
 
+       ATOMIC_INIT_NOTIFIER_HEAD(&nop->phy.notifier);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(usb_phy_gen_create_phy);
+
+void usb_phy_gen_cleanup_phy(struct usb_phy_gen_xceiv *nop)
+{
+       if (!IS_ERR(nop->clk))
+               clk_unprepare(nop->clk);
+}
+EXPORT_SYMBOL_GPL(usb_phy_gen_cleanup_phy);
+
+static int usb_phy_gen_xceiv_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct usb_phy_gen_xceiv_platform_data *pdata =
+                       dev_get_platdata(&pdev->dev);
+       struct usb_phy_gen_xceiv        *nop;
+       enum usb_phy_type       type = USB_PHY_TYPE_USB2;
+       int err;
+       u32 clk_rate = 0;
+       bool needs_vcc = false;
+       bool needs_reset = false;
+
+       if (dev->of_node) {
+               struct device_node *node = dev->of_node;
+
+               if (of_property_read_u32(node, "clock-frequency", &clk_rate))
+                       clk_rate = 0;
+
+               needs_vcc = of_property_read_bool(node, "vcc-supply");
+               needs_reset = of_property_read_bool(node, "reset-supply");
+
+       } else if (pdata) {
+               type = pdata->type;
+               clk_rate = pdata->clk_rate;
+               needs_vcc = pdata->needs_vcc;
+               needs_reset = pdata->needs_reset;
+       }
+
+       nop = devm_kzalloc(dev, sizeof(*nop), GFP_KERNEL);
+       if (!nop)
+               return -ENOMEM;
+
+
+       err = usb_phy_gen_create_phy(dev, nop, type, clk_rate, needs_vcc,
+                       needs_reset);
+       if (err)
+               return err;
+
+       nop->phy.init           = usb_gen_phy_init;
+       nop->phy.shutdown       = usb_gen_phy_shutdown;
+
        err = usb_add_phy_dev(&nop->phy);
        if (err) {
                dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
@@ -236,13 +257,10 @@ static int usb_phy_gen_xceiv_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, nop);
 
-       ATOMIC_INIT_NOTIFIER_HEAD(&nop->phy.notifier);
-
        return 0;
 
 err_add:
-       if (!IS_ERR(nop->clk))
-               clk_unprepare(nop->clk);
+       usb_phy_gen_cleanup_phy(nop);
        return err;
 }
 
@@ -250,9 +268,7 @@ static int usb_phy_gen_xceiv_remove(struct platform_device *pdev)
 {
        struct usb_phy_gen_xceiv *nop = platform_get_drvdata(pdev);
 
-       if (!IS_ERR(nop->clk))
-               clk_unprepare(nop->clk);
-
+       usb_phy_gen_cleanup_phy(nop);
        usb_remove_phy(&nop->phy);
 
        return 0;
diff --git a/drivers/usb/phy/phy-generic.h b/drivers/usb/phy/phy-generic.h
new file mode 100644 (file)
index 0000000..61687d5
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _PHY_GENERIC_H_
+#define _PHY_GENERIC_H_
+
+struct usb_phy_gen_xceiv {
+       struct usb_phy phy;
+       struct device *dev;
+       struct clk *clk;
+       struct regulator *vcc;
+       struct regulator *reset;
+};
+
+int usb_gen_phy_init(struct usb_phy *phy);
+void usb_gen_phy_shutdown(struct usb_phy *phy);
+
+int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop,
+               enum usb_phy_type type, u32 clk_rate, bool needs_vcc,
+               bool needs_reset);
+void usb_phy_gen_cleanup_phy(struct usb_phy_gen_xceiv *nop);
+
+#endif