From e3ec3eb79481d23b7d371b6e9567e2b6972efc92 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 19 Jul 2012 13:50:44 +0300 Subject: usb: dwc3: pci: add nop transceiver support We will be adding support for transceivers on dwc3 driver but not all boards have controllable transceivers. For those which don't provide controllable transceivers we will register nop transceivers. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-pci.c | 67 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index a9ca9adba391..94f550e37f98 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -42,6 +42,9 @@ #include #include +#include +#include + #include "core.h" /* FIXME define these in */ @@ -51,8 +54,64 @@ struct dwc3_pci { struct device *dev; struct platform_device *dwc3; + struct platform_device *usb2_phy; + struct platform_device *usb3_phy; }; +static int __devinit dwc3_pci_register_phys(struct dwc3_pci *glue) +{ + struct nop_usb_xceiv_platform_data pdata; + struct platform_device *pdev; + int ret; + + memset(&pdata, 0x00, sizeof(pdata)); + + pdev = platform_device_alloc("nop_usb_xceiv", 0); + if (!pdev) + return -ENOMEM; + + glue->usb2_phy = pdev; + pdata.type = USB_PHY_TYPE_USB2; + + ret = platform_device_add_data(glue->usb2_phy, &pdata, sizeof(pdata)); + if (ret) + goto err1; + + pdev = platform_device_alloc("nop_usb_xceiv", 1); + if (!pdev) { + ret = -ENOMEM; + goto err1; + } + + glue->usb3_phy = pdev; + pdata.type = USB_PHY_TYPE_USB3; + + ret = platform_device_add_data(glue->usb3_phy, &pdata, sizeof(pdata)); + if (ret) + goto err2; + + ret = platform_device_add(glue->usb2_phy); + if (ret) + goto err2; + + ret = platform_device_add(glue->usb3_phy); + if (ret) + goto err3; + + return 0; + +err3: + platform_device_del(glue->usb2_phy); + +err2: + platform_device_put(glue->usb3_phy); + +err1: + platform_device_put(glue->usb2_phy); + + return ret; +} + static int __devinit dwc3_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) { @@ -80,6 +139,12 @@ static int __devinit dwc3_pci_probe(struct pci_dev *pci, pci_set_power_state(pci, PCI_D0); pci_set_master(pci); + ret = dwc3_pci_register_phys(glue); + if (ret) { + dev_err(dev, "couldn't register PHYs\n"); + return ret; + } + devid = dwc3_get_device_id(); if (devid < 0) { ret = -ENOMEM; @@ -144,6 +209,8 @@ static void __devexit dwc3_pci_remove(struct pci_dev *pci) { struct dwc3_pci *glue = pci_get_drvdata(pci); + platform_device_unregister(glue->usb2_phy); + platform_device_unregister(glue->usb3_phy); dwc3_put_device_id(glue->dwc3->id); platform_device_unregister(glue->dwc3); pci_set_drvdata(pci, NULL); -- cgit v1.2.3 From a418cc4ea552884e9f2aa875aaa0afa1f0ffe07d Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 19 Jul 2012 13:56:07 +0300 Subject: usb: dwc3: omap: add nop transceiver support We will be adding support for transceivers on dwc3 driver but not all boards have controllable transceivers. For those which don't provide controllable transceivers we will register nop transceivers. Note that once OMAP's transceiver drivers reach mainline, this glue layer will change accordingly. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-omap.c | 66 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 479dc047da3a..ee57a10d90d0 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -48,6 +48,9 @@ #include #include +#include +#include + #include "core.h" /* @@ -131,6 +134,8 @@ struct dwc3_omap { spinlock_t lock; struct platform_device *dwc3; + struct platform_device *usb2_phy; + struct platform_device *usb3_phy; struct device *dev; int irq; @@ -152,6 +157,59 @@ static inline void dwc3_omap_writel(void __iomem *base, u32 offset, u32 value) writel(value, base + offset); } +static int __devinit dwc3_omap_register_phys(struct dwc3_omap *omap) +{ + struct nop_usb_xceiv_platform_data pdata; + struct platform_device *pdev; + int ret; + + memset(&pdata, 0x00, sizeof(pdata)); + + pdev = platform_device_alloc("nop_usb_xceiv", 0); + if (!pdev) + return -ENOMEM; + + omap->usb2_phy = pdev; + pdata.type = USB_PHY_TYPE_USB2; + + ret = platform_device_add_data(omap->usb2_phy, &pdata, sizeof(pdata)); + if (ret) + goto err1; + + pdev = platform_device_alloc("nop_usb_xceiv", 1); + if (!pdev) { + ret = -ENOMEM; + goto err1; + } + + omap->usb3_phy = pdev; + pdata.type = USB_PHY_TYPE_USB3; + + ret = platform_device_add_data(omap->usb3_phy, &pdata, sizeof(pdata)); + if (ret) + goto err2; + + ret = platform_device_add(omap->usb2_phy); + if (ret) + goto err2; + + ret = platform_device_add(omap->usb3_phy); + if (ret) + goto err3; + + return 0; + +err3: + platform_device_del(omap->usb2_phy); + +err2: + platform_device_put(omap->usb3_phy); + +err1: + platform_device_put(omap->usb2_phy); + + return ret; +} static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap) { @@ -251,6 +309,12 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev) return -ENOMEM; } + ret = dwc3_omap_register_phys(omap); + if (ret) { + dev_err(dev, "couldn't register PHYs\n"); + return ret; + } + devid = dwc3_get_device_id(); if (devid < 0) return -ENODEV; @@ -371,6 +435,8 @@ static int __devexit dwc3_omap_remove(struct platform_device *pdev) struct dwc3_omap *omap = platform_get_drvdata(pdev); platform_device_unregister(omap->dwc3); + platform_device_unregister(omap->usb2_phy); + platform_device_unregister(omap->usb3_phy); dwc3_put_device_id(omap->dwc3->id); -- cgit v1.2.3 From d720f057fda4bae91a5108a11587374b9e396c6a Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 19 Jul 2012 14:01:10 +0300 Subject: usb: dwc3: exynos: add nop transceiver support We will be adding support for transceivers on dwc3 driver but not all boards have controllable transceivers. For those which don't provide controllable transceivers we will register nop transceivers. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-exynos.c | 66 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c index b8f00389fa34..ca6597853f90 100644 --- a/drivers/usb/dwc3/dwc3-exynos.c +++ b/drivers/usb/dwc3/dwc3-exynos.c @@ -19,16 +19,74 @@ #include #include #include +#include +#include #include "core.h" struct dwc3_exynos { struct platform_device *dwc3; + struct platform_device *usb2_phy; + struct platform_device *usb3_phy; struct device *dev; struct clk *clk; }; +static int __devinit dwc3_exynos_register_phys(struct dwc3_exynos *exynos) +{ + struct nop_usb_xceiv_platform_data pdata; + struct platform_device *pdev; + int ret; + + memset(&pdata, 0x00, sizeof(pdata)); + + pdev = platform_device_alloc("nop_usb_xceiv", 0); + if (!pdev) + return -ENOMEM; + + exynos->usb2_phy = pdev; + pdata.type = USB_PHY_TYPE_USB2; + + ret = platform_device_add_data(exynos->usb2_phy, &pdata, sizeof(pdata)); + if (ret) + goto err1; + + pdev = platform_device_alloc("nop_usb_xceiv", 1); + if (!pdev) { + ret = -ENOMEM; + goto err1; + } + + exynos->usb3_phy = pdev; + pdata.type = USB_PHY_TYPE_USB3; + + ret = platform_device_add_data(exynos->usb3_phy, &pdata, sizeof(pdata)); + if (ret) + goto err2; + + ret = platform_device_add(exynos->usb2_phy); + if (ret) + goto err2; + + ret = platform_device_add(exynos->usb3_phy); + if (ret) + goto err3; + + return 0; + +err3: + platform_device_del(exynos->usb2_phy); + +err2: + platform_device_put(exynos->usb3_phy); + +err1: + platform_device_put(exynos->usb2_phy); + + return ret; +} + static int __devinit dwc3_exynos_probe(struct platform_device *pdev) { struct dwc3_exynos_data *pdata = pdev->dev.platform_data; @@ -51,6 +109,12 @@ static int __devinit dwc3_exynos_probe(struct platform_device *pdev) if (devid < 0) goto err1; + ret = dwc3_exynos_register_phys(exynos); + if (ret) { + dev_err(&pdev->dev, "couldn't register PHYs\n"); + goto err1; + } + dwc3 = platform_device_alloc("dwc3", devid); if (!dwc3) { dev_err(&pdev->dev, "couldn't allocate dwc3 device\n"); @@ -120,6 +184,8 @@ static int __devexit dwc3_exynos_remove(struct platform_device *pdev) struct dwc3_exynos_data *pdata = pdev->dev.platform_data; platform_device_unregister(exynos->dwc3); + platform_device_unregister(exynos->usb2_phy); + platform_device_unregister(exynos->usb3_phy); dwc3_put_device_id(exynos->dwc3->id); -- cgit v1.2.3 From 51e1e7bcef53e6a91cfffff0145ab315def61f61 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 19 Jul 2012 14:09:48 +0300 Subject: usb: dwc3: add basic PHY support this will let us control PHYs on platforms which need them. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 15 +++++++++++++++ drivers/usb/dwc3/core.h | 5 +++++ 2 files changed, 20 insertions(+) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index c34452a7304f..79a24fab13d1 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -50,6 +50,7 @@ #include #include +#include #include #include @@ -136,6 +137,8 @@ static void dwc3_core_soft_reset(struct dwc3 *dwc) reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST; dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); + usb_phy_init(dwc->usb2_phy); + usb_phy_init(dwc->usb3_phy); mdelay(100); /* Clear USB3 PHY reset */ @@ -465,6 +468,18 @@ static int __devinit dwc3_probe(struct platform_device *pdev) return -ENOMEM; } + dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); + if (IS_ERR_OR_NULL(dwc->usb2_phy)) { + dev_err(dev, "no usb2 phy configured\n"); + return -EPROBE_DEFER; + } + + dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); + if (IS_ERR_OR_NULL(dwc->usb3_phy)) { + dev_err(dev, "no usb3 phy configured\n"); + return -EPROBE_DEFER; + } + spin_lock_init(&dwc->lock); platform_set_drvdata(pdev, dwc); diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 151eca876dfd..dbc5713d84fb 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -624,6 +624,8 @@ struct dwc3_scratchpad_array { * @maximum_speed: maximum speed requested (mainly for testing purposes) * @revision: revision register contents * @mode: mode of operation + * @usb2_phy: pointer to USB2 PHY + * @usb3_phy: pointer to USB3 PHY * @is_selfpowered: true when we are selfpowered * @three_stage_setup: set if we perform a three phase setup * @ep0_bounced: true when we used bounce buffer @@ -667,6 +669,9 @@ struct dwc3 { struct usb_gadget gadget; struct usb_gadget_driver *gadget_driver; + struct usb_phy *usb2_phy; + struct usb_phy *usb3_phy; + void __iomem *regs; size_t regs_size; -- cgit v1.2.3