Todo: binding document, more properties
Signed-off-by: Uwe Kleine-König <[email protected]>
---
drivers/usb/phy/phy-ulpi.c | 129 +++++++++++++++++++++++++++++++++++++++++----
1 file changed, 119 insertions(+), 10 deletions(-)
diff --git a/drivers/usb/phy/phy-ulpi.c b/drivers/usb/phy/phy-ulpi.c
index f48a7a21e3c2..b7f9a091834c 100644
--- a/drivers/usb/phy/phy-ulpi.c
+++ b/drivers/usb/phy/phy-ulpi.c
@@ -23,13 +23,16 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <asm/io.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/usb.h>
#include <linux/usb/otg.h>
#include <linux/usb/ulpi.h>
-
+#include <linux/of.h>
struct ulpi_info {
unsigned int id;
@@ -253,6 +256,20 @@ static int ulpi_set_vbus(struct usb_otg *otg, bool on)
return usb_phy_io_write(phy, flags, ULPI_OTG_CTRL);
}
+static void otg_ulpi_init(struct usb_phy *phy, struct usb_otg *otg,
+ struct usb_phy_io_ops *ops, unsigned int flags)
+{
+ phy->label = "ULPI";
+ phy->flags = flags;
+ phy->io_ops = ops;
+ phy->otg = otg;
+ phy->init = ulpi_init;
+
+ otg->usb_phy = phy;
+ otg->set_host = ulpi_set_host;
+ otg->set_vbus = ulpi_set_vbus;
+}
+
struct usb_phy *
otg_ulpi_create(struct usb_phy_io_ops *ops,
unsigned int flags)
@@ -270,17 +287,109 @@ otg_ulpi_create(struct usb_phy_io_ops *ops,
return NULL;
}
- phy->label = "ULPI";
- phy->flags = flags;
- phy->io_ops = ops;
- phy->otg = otg;
- phy->init = ulpi_init;
-
- otg->usb_phy = phy;
- otg->set_host = ulpi_set_host;
- otg->set_vbus = ulpi_set_vbus;
+ otg_ulpi_init(phy, otg, ops, flags);
return phy;
}
EXPORT_SYMBOL_GPL(otg_ulpi_create);
+struct usb_phy_ulpi_ddata {
+ void __iomem *base;
+ struct usb_phy usbphy;
+ struct usb_otg otg;
+};
+
+static const struct phy_ops usb_phy_ulpi_phy_ops = {
+ .owner = THIS_MODULE,
+};
+
+static void usb_phy_init_dt(struct device_node *np,
+ struct usb_phy_ulpi_ddata *ddata)
+{
+ struct usb_phy *usbphy = &ddata->usbphy;
+
+
+ /* some bits are missing ... */
+ if (of_get_property(np, "ulpi,otg-id-pullup", NULL))
+ usbphy->flags |= ULPI_OTG_ID_PULLUP;
+
+ if (of_get_property(np, "ulpi,otg-dp-pulldown-disable", NULL))
+ usbphy->flags |= ULPI_OTG_DP_PULLDOWN_DIS;
+
+ if (of_get_property(np, "ulpi,otg-dm-pulldown-disable", NULL))
+ usbphy->flags |= ULPI_OTG_DM_PULLDOWN_DIS;
+
+ if (of_get_property(np, "ulpi,otg-external-vbus", NULL))
+ usbphy->flags |= ULPI_OTG_DRVVBUS_EXT;
+
+ if (of_get_property(np, "ulpi,otg-external-overcurrent-indicator",
NULL))
+ usbphy->flags |= ULPI_OTG_EXTVBUSIND;
+}
+
+static int usb_phy_ulpi_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct phy *phy;
+ struct phy_provider *phy_provider;
+ struct usb_phy_ulpi_ddata *ddata;
+ int err;
+
+ ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
+ if (!ddata)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, ddata);
+
+ otg_ulpi_init(&ddata->usbphy, &ddata->otg, NULL, 0);
+
+ ddata->usbphy.io_priv = NULL;
+ ddata->usbphy.dev = dev;
+
+ usb_phy_init_dt(dev->of_node, ddata);
+
+ phy = devm_phy_create(dev, NULL, &usb_phy_ulpi_phy_ops);
+ if (IS_ERR(phy)) {
+ err = PTR_ERR(phy);
+ dev_err(dev, "can't create phy device, err: %d\n", err);
+ return err;
+ }
+
+ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+ if (IS_ERR(phy_provider)) {
+ err = PTR_ERR(phy_provider);
+ dev_err(dev, "can't create phy provider, err: %d\n", err);
+ return err;
+ }
+
+ err = usb_add_phy_dev(&ddata->usbphy);
+ if (err) {
+ dev_err(dev, "can't register usb_phy device, err: %d\n", err);
+ return err;
+ }
+
+ return 0;
+}
+
+static int usb_phy_ulpi_remove(struct platform_device *pdev)
+{
+ struct usb_phy_ulpi_ddata *ddata = platform_get_drvdata(pdev);
+
+ usb_remove_phy(&ddata->usbphy);
+
+ return 0;
+}
+
+static const struct of_device_id usb_phy_ulpi_ids[] = {
+ { .compatible = "usb-ulpi-xceiv" },
+ { /* sentinel */ }
+};
+
+static struct platform_driver usb_phy_ulpi_driver = {
+ .probe = usb_phy_ulpi_probe,
+ .remove = usb_phy_ulpi_remove,
+ .driver = {
+ .name = "usb-phy-ulpi",
+ .of_match_table = usb_phy_ulpi_ids,
+ },
+};
+module_platform_driver(usb_phy_ulpi_driver);
--
2.6.2
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html