usb: phy: phy-generic: export init functions
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>
diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c
index 406f8e4..efe59f3 100644
--- a/drivers/usb/phy/phy-generic.c
+++ b/drivers/usb/phy/phy-generic.c
@@ -36,13 +36,7 @@
#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 @@
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 @@
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 @@
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,6 +135,78 @@
return 0;
}
+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)
+{
+ int err;
+
+ nop->phy.otg = devm_kzalloc(dev, sizeof(*nop->phy.otg),
+ GFP_KERNEL);
+ if (!nop->phy.otg)
+ return -ENOMEM;
+
+ nop->clk = devm_clk_get(dev, "main_clk");
+ if (IS_ERR(nop->clk)) {
+ 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(dev, "Error setting clock rate\n");
+ return err;
+ }
+ }
+
+ if (!IS_ERR(nop->clk)) {
+ err = clk_prepare(nop->clk);
+ if (err) {
+ dev_err(dev, "Error preparing clock\n");
+ return err;
+ }
+ }
+
+ nop->vcc = devm_regulator_get(dev, "vcc");
+ if (IS_ERR(nop->vcc)) {
+ dev_dbg(dev, "Error getting vcc regulator: %ld\n",
+ PTR_ERR(nop->vcc));
+ if (needs_vcc)
+ return -EPROBE_DEFER;
+ }
+
+ nop->reset = devm_regulator_get(dev, "reset");
+ if (IS_ERR(nop->reset)) {
+ dev_dbg(dev, "Error getting reset regulator: %ld\n",
+ PTR_ERR(nop->reset));
+ if (needs_reset)
+ return -EPROBE_DEFER;
+ }
+
+ nop->dev = dev;
+ nop->phy.dev = nop->dev;
+ nop->phy.label = "nop-xceiv";
+ nop->phy.set_suspend = nop_set_suspend;
+ nop->phy.state = OTG_STATE_UNDEFINED;
+ nop->phy.type = type;
+
+ nop->phy.otg->phy = &nop->phy;
+ 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;
@@ -151,15 +219,6 @@
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);
- if (!nop->phy.otg)
- return -ENOMEM;
-
if (dev->of_node) {
struct device_node *node = dev->of_node;
@@ -176,56 +235,18 @@
needs_reset = pdata->needs_reset;
}
- nop->clk = devm_clk_get(&pdev->dev, "main_clk");
- if (IS_ERR(nop->clk)) {
- dev_dbg(&pdev->dev, "Can't get phy clock: %ld\n",
- PTR_ERR(nop->clk));
- }
+ nop = devm_kzalloc(dev, sizeof(*nop), GFP_KERNEL);
+ if (!nop)
+ return -ENOMEM;
- 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");
- return err;
- }
- }
- if (!IS_ERR(nop->clk)) {
- err = clk_prepare(nop->clk);
- if (err) {
- dev_err(&pdev->dev, "Error preparing clock\n");
- return err;
- }
- }
+ err = usb_phy_gen_create_phy(dev, nop, type, clk_rate, needs_vcc,
+ needs_reset);
+ if (err)
+ return err;
- nop->vcc = devm_regulator_get(&pdev->dev, "vcc");
- if (IS_ERR(nop->vcc)) {
- dev_dbg(&pdev->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");
- if (IS_ERR(nop->reset)) {
- dev_dbg(&pdev->dev, "Error getting reset regulator: %ld\n",
- PTR_ERR(nop->reset));
- if (needs_reset)
- return -EPROBE_DEFER;
- }
-
- nop->dev = &pdev->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;
-
- nop->phy.otg->phy = &nop->phy;
- nop->phy.otg->set_host = nop_set_host;
- nop->phy.otg->set_peripheral = nop_set_peripheral;
+ nop->phy.init = usb_gen_phy_init;
+ nop->phy.shutdown = usb_gen_phy_shutdown;
err = usb_add_phy_dev(&nop->phy);
if (err) {
@@ -236,13 +257,10 @@
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 @@
{
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
index 0000000..61687d5
--- /dev/null
+++ b/drivers/usb/phy/phy-generic.h
@@ -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