123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- --- a/drivers/usb/phy/Kconfig
- +++ b/drivers/usb/phy/Kconfig
- @@ -202,6 +202,7 @@ config USB_RCAR_PHY
- config USB_ULPI
- bool "Generic ULPI Transceiver Driver"
- depends on ARM || ARM64
- + depends on USB_PHY
- select USB_ULPI_VIEWPORT
- help
- Enable this to support ULPI connected USB OTG transceivers which
- --- a/drivers/usb/phy/phy-ulpi.c
- +++ b/drivers/usb/phy/phy-ulpi.c
- @@ -26,9 +26,16 @@
- #include <linux/kernel.h>
- #include <linux/slab.h>
- #include <linux/export.h>
- +#include <linux/module.h>
- +#include <linux/of.h>
- +#include <linux/io.h>
- +#include <linux/of_address.h>
- +#include <linux/of_device.h>
- +#include <linux/platform_device.h>
- #include <linux/usb.h>
- #include <linux/usb/otg.h>
- #include <linux/usb/ulpi.h>
- +#include <linux/usb/phy.h>
-
-
- struct ulpi_info {
- @@ -52,6 +59,13 @@ static struct ulpi_info ulpi_ids[] = {
- ULPI_INFO(ULPI_ID(0x0451, 0x1507), "TI TUSB1210"),
- };
-
- +struct ulpi_phy {
- + struct usb_phy *usb_phy;
- + void __iomem *regs;
- + unsigned int vp_offset;
- + unsigned int flags;
- +};
- +
- static int ulpi_set_otg_flags(struct usb_phy *phy)
- {
- unsigned int flags = ULPI_OTG_CTRL_DP_PULLDOWN |
- @@ -253,6 +267,23 @@ static int ulpi_set_vbus(struct usb_otg
- return usb_phy_io_write(phy, flags, ULPI_OTG_CTRL);
- }
-
- +static int usbphy_set_vbus(struct usb_phy *phy, int on)
- +{
- + unsigned int flags = usb_phy_io_read(phy, ULPI_OTG_CTRL);
- +
- + flags &= ~(ULPI_OTG_CTRL_DRVVBUS | ULPI_OTG_CTRL_DRVVBUS_EXT);
- +
- + if (on) {
- + if (phy->flags & ULPI_OTG_DRVVBUS)
- + flags |= ULPI_OTG_CTRL_DRVVBUS;
- +
- + if (phy->flags & ULPI_OTG_DRVVBUS_EXT)
- + flags |= ULPI_OTG_CTRL_DRVVBUS_EXT;
- + }
- +
- + return usb_phy_io_write(phy, flags, ULPI_OTG_CTRL);
- +}
- +
- struct usb_phy *
- otg_ulpi_create(struct usb_phy_io_ops *ops,
- unsigned int flags)
- @@ -275,6 +306,7 @@ otg_ulpi_create(struct usb_phy_io_ops *o
- phy->io_ops = ops;
- phy->otg = otg;
- phy->init = ulpi_init;
- + phy->set_vbus = usbphy_set_vbus;
-
- otg->usb_phy = phy;
- otg->set_host = ulpi_set_host;
- @@ -284,3 +316,70 @@ otg_ulpi_create(struct usb_phy_io_ops *o
- }
- EXPORT_SYMBOL_GPL(otg_ulpi_create);
-
- +static int ulpi_phy_probe(struct platform_device *pdev)
- +{
- + struct device_node *np = pdev->dev.of_node;
- + struct resource *res;
- + struct ulpi_phy *uphy;
- + bool flag;
- + int ret;
- +
- + uphy = devm_kzalloc(&pdev->dev, sizeof(*uphy), GFP_KERNEL);
- + if (!uphy)
- + return -ENOMEM;
- +
- + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- + uphy->regs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
- + if (IS_ERR(uphy->regs))
- + return PTR_ERR(uphy->regs);
- +
- + ret = of_property_read_u32(np, "view-port", &uphy->vp_offset);
- + if (IS_ERR(uphy->regs)) {
- + dev_err(&pdev->dev, "view-port register not specified\n");
- + return PTR_ERR(uphy->regs);
- + }
- +
- + flag = of_property_read_bool(np, "drv-vbus");
- + if (flag)
- + uphy->flags |= ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT;
- +
- + uphy->usb_phy = otg_ulpi_create(&ulpi_viewport_access_ops, uphy->flags);
- +
- + uphy->usb_phy->dev = &pdev->dev;
- +
- + uphy->usb_phy->io_priv = uphy->regs + uphy->vp_offset;
- +
- + ret = usb_add_phy_dev(uphy->usb_phy);
- + if (ret < 0)
- + return ret;
- +
- + return 0;
- +}
- +
- +static int ulpi_phy_remove(struct platform_device *pdev)
- +{
- + struct ulpi_phy *uphy = platform_get_drvdata(pdev);
- +
- + usb_remove_phy(uphy->usb_phy);
- +
- + return 0;
- +}
- +
- +static const struct of_device_id ulpi_phy_table[] = {
- + { .compatible = "ulpi-phy" },
- + { },
- +};
- +MODULE_DEVICE_TABLE(of, ulpi_phy_table);
- +
- +static struct platform_driver ulpi_phy_driver = {
- + .probe = ulpi_phy_probe,
- + .remove = ulpi_phy_remove,
- + .driver = {
- + .name = "ulpi-phy",
- + .of_match_table = ulpi_phy_table,
- + },
- +};
- +module_platform_driver(ulpi_phy_driver);
- +
- +MODULE_DESCRIPTION("ULPI PHY driver");
- +MODULE_LICENSE("GPL v2");
|