lkml.org 
[lkml]   [2013]   [Dec]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH RFC 3/4] xhci: Tune PHY for the DWC3-Exynos host controller
Date
The DWC3-exynos eXtensible host controller on Exynos5420 SoC
is quirky in a way that the PHY needs to be tuned to get it
working at SuperSpeed.
Add relevant calls for tuning the PHY for DWC3-Exynos's
host controller, for that matter passing just USB3 PHY
from DWC3 core, which is saved in secondary HCD of XHCI.

Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
---
drivers/usb/dwc3/host.c | 7 ++++++
drivers/usb/host/xhci-plat.c | 43 ++++++++++++++++++++++++++++++++++++++++-
include/linux/usb/hcd.h | 1 +
3 files changed, 49 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
index 32db328..cc1f6ff 100644
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -46,6 +46,13 @@ int dwc3_host_init(struct dwc3 *dwc)
goto err1;
}

+ ret = platform_device_add_data(xhci, &dwc->usb3_generic_phy,
+ sizeof(dwc->usb3_generic_phy));
+ if (ret) {
+ dev_err(dwc->dev, "failed to add platform data\n");
+ goto err1;
+ }
+
ret = platform_device_add(xhci);
if (ret) {
dev_err(dwc->dev, "failed to register xHCI device\n");
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 395c9e9..a0f3cbc 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -16,6 +16,7 @@
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/dma-mapping.h>
+#include <linux/phy/phy.h>

#include "xhci.h"

@@ -51,7 +52,24 @@ static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci)
/* called during probe() after chip reset completes */
static int xhci_plat_setup(struct usb_hcd *hcd)
{
- return xhci_gen_setup(hcd, xhci_plat_quirks);
+ struct xhci_hcd *xhci;
+ int ret = 0;
+
+ ret = xhci_gen_setup(hcd, xhci_plat_quirks);
+ if (ret) {
+ dev_err(hcd->self.controller, "xhci setup failed\n");
+ goto err0;
+ }
+
+ /* Valid for secondary HCD only which gives SuperSpeed ports */
+ if (!usb_hcd_is_primary_hcd(hcd)) {
+ xhci = hcd_to_xhci(hcd);
+ if (xhci->quirks & XHCI_DWC3_EXYNOS)
+ phy_tune(hcd->phy_generic);
+ }
+
+err0:
+ return ret;
}

static const struct hc_driver xhci_plat_xhci_driver = {
@@ -111,6 +129,7 @@ static int xhci_plat_probe(struct platform_device *pdev)
struct usb_hcd *hcd;
int ret;
int irq;
+ struct phy **phy_generic;

if (usb_disabled())
return -ENODEV;
@@ -170,6 +189,15 @@ static int xhci_plat_probe(struct platform_device *pdev)
}

/*
+ * The parent of the xhci-plat device may pass in a PHY via
+ * platform data. If it exists, store it in our struct usb_hcd
+ * so that we can use it later.
+ */
+ phy_generic = dev_get_platdata(&pdev->dev);
+ if (phy_generic)
+ xhci->shared_hcd->phy_generic = *phy_generic;
+
+ /*
* Set the xHCI pointer before xhci_plat_setup() (aka hcd_driver.reset)
* is called by usb_add_hcd().
*/
@@ -229,8 +257,19 @@ static int xhci_plat_resume(struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ int ret;
+
+ ret = xhci_resume(xhci, 0);
+ if (ret)
+ return ret;

- return xhci_resume(xhci, 0);
+ /* Valid for secondary HCD only which gives SuperSpeed ports */
+ if (!usb_hcd_is_primary_hcd(hcd)) {
+ if (xhci->quirks & XHCI_DWC3_EXYNOS)
+ phy_tune(hcd->phy_generic);
+ }
+
+ return 0;
}

static const struct dev_pm_ops xhci_plat_pm_ops = {
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index b8aba19..241ed2b 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -107,6 +107,7 @@ struct usb_hcd {
* other external phys should be software-transparent
*/
struct usb_phy *phy;
+ struct phy *phy_generic;

/* Flags that need to be manipulated atomically because they can
* change while the host controller is running. Always use
--
1.7.6.5


\
 
 \ /
  Last update: 2013-12-10 12:21    [W:0.124 / U:0.184 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site