diff options
Diffstat (limited to 'target/linux/zynq/patches/110-add-platform-driver-support-for-ulpi-phys.patch')
-rw-r--r-- | target/linux/zynq/patches/110-add-platform-driver-support-for-ulpi-phys.patch | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/target/linux/zynq/patches/110-add-platform-driver-support-for-ulpi-phys.patch b/target/linux/zynq/patches/110-add-platform-driver-support-for-ulpi-phys.patch new file mode 100644 index 0000000000..b2eb6aa5b7 --- /dev/null +++ b/target/linux/zynq/patches/110-add-platform-driver-support-for-ulpi-phys.patch @@ -0,0 +1,146 @@ +--- 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"); |