All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 0/4] Fine tune USB 3.0 PHY on exynos5420
@ 2014-08-21 14:55 Vivek Gautam
  2014-08-21 14:55 ` [PATCH v5 1/4] phy: Add provision for calibrating phy Vivek Gautam
                   ` (3 more replies)
  0 siblings, 4 replies; 12+ messages in thread
From: Vivek Gautam @ 2014-08-21 14:55 UTC (permalink / raw)
  To: linux-usb
  Cc: linux-samsung-soc, linux-kernel, gregkh, kishon, kgene.kim,
	mathias.nyman, stern, sergei.shtylyov, heikki.krogerus, balbi,
	Vivek Gautam

This series is based on Heikki's patches for simpliefied phy lookup table:
[PATCHv3 0/6] phy: simplified phy lookup [1], applied against 'usb-next' branch
alongwith Sergei's patch for adding generic phy support to usb hcd [2].

Changes since v4:
 - Rebased on latest patches by Heikki.
 - Took care of handling -EPROBE_DEFER error number while getting PHY in
   xhci plat.

Changes from v3:
 - Modified error message as per review comments from Julius.

Changes since v2:
 - Removed any check for DWC3 in xhci-plat for getting usb2-phy and usb3-phy,
   in order to make it more generic.
 - Moved the phy_calibration calls to core/hcd.c to enable a more generic
   solution for issues of calibrating the PHYs.

Changes since v1:
 - Using 'gen_phy' member of 'hcd' instead of declaring more variables
   to hold phys.
 - Added a check for compatible match for 'Synopsys-dwc3' controller,
   since the 'gen_phy' member of 'hcd' already gets the 'usb' PHY
   in core/hcd.c; but XHCI on Synopsys-dwc3 doesn't need that,
   instead two separate PHYs for UTMI+ and PIPE3 for the two HCDs
   (main hcd and shared hcd).
 - Restructured the code in 'xhci_plat_setup()' and 'xhci_plat_resume()'
   to use hcd->gen_phy directly. Also added the check for Synopsys's DWC3
   controller while trying to calibrate the PHY.

Explanation for the need of this patch-series:
"The DWC3-exynos eXtensible host controller present on Exynos5420/5800
SoCs is quirky. The PHY serving this controller operates at High-Speed
by default, so it detects even Super-speed devices as high-speed ones.
Certain PHY parameters like Tx LOS levels and Boost levels need to be
calibrated further post initialization of xHCI controller, to get
SuperSpeed operations working."

[1] https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg710094.html
[2] http://comments.gmane.org/gmane.linux.ports.sh.devel/35932

Vivek Gautam (4):
  phy: Add provision for calibrating phy.
  usb: host: xhci-plat: Get PHYs for xhci's hcds
  usb: hcd: Caibrate PHY post hcd reset
  phy: exynos5-usbdrd: Calibrate LOS levels for exynos5420/5800

 drivers/phy/phy-core.c           |   36 ++++++++
 drivers/phy/phy-exynos5-usbdrd.c |  169 ++++++++++++++++++++++++++++++++++++++
 drivers/usb/core/hcd.c           |   22 +++++
 drivers/usb/host/xhci-plat.c     |   23 ++++++
 include/linux/phy/phy.h          |    8 ++
 5 files changed, 258 insertions(+)

-- 
1.7.10.4


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v5 1/4] phy: Add provision for calibrating phy.
  2014-08-21 14:55 [PATCH v5 0/4] Fine tune USB 3.0 PHY on exynos5420 Vivek Gautam
@ 2014-08-21 14:55 ` Vivek Gautam
  2014-08-21 14:55 ` [PATCH v5 2/4] usb: host: xhci-plat: Get PHYs for xhci's hcds Vivek Gautam
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 12+ messages in thread
From: Vivek Gautam @ 2014-08-21 14:55 UTC (permalink / raw)
  To: linux-usb
  Cc: linux-samsung-soc, linux-kernel, gregkh, kishon, kgene.kim,
	mathias.nyman, stern, sergei.shtylyov, heikki.krogerus, balbi,
	Vivek Gautam

Some PHY controllers may need to calibrate certain
PHY settings after initialization of the controller and
sometimes even after initializing the PHY-consumer too.
Add support for the same in order to let consumers do so in need.

Signed-off-by: vivek Gautam <gautam.vivek@samsung.com>
---
 drivers/phy/phy-core.c  |   36 ++++++++++++++++++++++++++++++++++++
 include/linux/phy/phy.h |    8 ++++++++
 2 files changed, 44 insertions(+)

diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index 834b337..c8cb3de 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -393,6 +393,42 @@ int phy_power_off(struct phy *phy)
 EXPORT_SYMBOL_GPL(phy_power_off);
 
 /**
+ * phy_calibrate - calibrate a phy post initialization
+ * @phy: Pointer to 'phy' from consumer
+ *
+ * For certain PHYs, it may be needed to calibrate few phy parameters
+ * post initialization. The need to calibrate may arise after the
+ * initialization of consumer itself, in order to prevent further any
+ * loss of phy settings post consumer-initialization.
+ *	example: USB 3.0 DRD PHY on Exynos5420/5800 systems is one such
+ *	phy which needs calibration after the host controller reset
+ *	has happened.
+ */
+int phy_calibrate(struct phy *phy)
+{
+	int ret = -ENOTSUPP;
+
+	if (!phy)
+		return 0;
+
+	mutex_lock(&phy->mutex);
+	if (phy->ops->calibrate) {
+		ret =  phy->ops->calibrate(phy);
+		if (ret < 0) {
+			dev_err(&phy->dev,
+				"phy calibration failed --> %d\n", ret);
+			goto out;
+		}
+	}
+
+out:
+	mutex_unlock(&phy->mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(phy_calibrate);
+
+/**
  * _of_phy_get() - lookup and obtain a reference to a phy by phandle
  * @np: device_node for which to get the phy
  * @index: the index of the phy
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
index d983051..c70a311 100644
--- a/include/linux/phy/phy.h
+++ b/include/linux/phy/phy.h
@@ -28,6 +28,7 @@ struct phy;
  * @exit: operation to be performed while exiting
  * @power_on: powering on the phy
  * @power_off: powering off the phy
+ * @calibrate: calibrate the phy post init
  * @owner: the module owner containing the ops
  */
 struct phy_ops {
@@ -35,6 +36,7 @@ struct phy_ops {
 	int	(*exit)(struct phy *phy);
 	int	(*power_on)(struct phy *phy);
 	int	(*power_off)(struct phy *phy);
+	int	(*calibrate)(struct phy *phy);
 	struct module *owner;
 };
 
@@ -126,6 +128,7 @@ int phy_init(struct phy *phy);
 int phy_exit(struct phy *phy);
 int phy_power_on(struct phy *phy);
 int phy_power_off(struct phy *phy);
+int phy_calibrate(struct phy *phy);
 static inline int phy_get_bus_width(struct phy *phy)
 {
 	return phy->attrs.bus_width;
@@ -231,6 +234,11 @@ static inline int phy_power_off(struct phy *phy)
 	return -ENOSYS;
 }
 
+static inline int phy_calibrate(struct phy *phy)
+{
+	return -ENOSYS;
+}
+
 static inline int phy_get_bus_width(struct phy *phy)
 {
 	return -ENOSYS;
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v5 2/4] usb: host: xhci-plat: Get PHYs for xhci's hcds
  2014-08-21 14:55 [PATCH v5 0/4] Fine tune USB 3.0 PHY on exynos5420 Vivek Gautam
  2014-08-21 14:55 ` [PATCH v5 1/4] phy: Add provision for calibrating phy Vivek Gautam
@ 2014-08-21 14:55 ` Vivek Gautam
  2014-08-21 14:55 ` [PATCH v5 3/4] usb: hcd: Caibrate PHY post hcd reset Vivek Gautam
  2014-08-21 14:55 ` [PATCH v5 4/4] phy: exynos5-usbdrd: Calibrate LOS levels for exynos5420/5800 Vivek Gautam
  3 siblings, 0 replies; 12+ messages in thread
From: Vivek Gautam @ 2014-08-21 14:55 UTC (permalink / raw)
  To: linux-usb
  Cc: linux-samsung-soc, linux-kernel, gregkh, kishon, kgene.kim,
	mathias.nyman, stern, sergei.shtylyov, heikki.krogerus, balbi,
	Vivek Gautam

The host controller by itself may sometimes need to handle PHY
and/or calibrate some of the PHY settings to get full support out
of the PHY controller. The PHY core provides a calibration
funtionality now to do so.
Therefore, facilitate getting the two possible PHYs, viz.
USB 2.0 type (UTMI+) and USB 3.0 type (PIPE3).

Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
---
 drivers/usb/host/xhci-plat.c |   23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 1a0cf9f..56ef9cf 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
+#include <linux/phy/phy.h>
 #include <linux/slab.h>
 #include <linux/usb/xhci_pdriver.h>
 
@@ -180,6 +181,17 @@ static int xhci_plat_probe(struct platform_device *pdev)
 			goto put_hcd;
 	}
 
+	/* Get possile USB 2.0 type PHY (UTMI+) available with xhci */
+	hcd->gen_phy = devm_phy_get(&pdev->dev, "usb2-phy");
+	if (IS_ERR(hcd->gen_phy)) {
+		ret = PTR_ERR(hcd->gen_phy);
+		if (ret == -EPROBE_DEFER)
+			return ret;
+		else if (ret != -ENOSYS && ret != -ENODEV)
+			dev_warn(&pdev->dev,
+				 "Error retrieving usb2 phy: %d\n", ret);
+	}
+
 	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
 	if (ret)
 		goto disable_clk;
@@ -209,6 +221,17 @@ static int xhci_plat_probe(struct platform_device *pdev)
 	if (HCC_MAX_PSA(xhci->hcc_params) >= 4)
 		xhci->shared_hcd->can_do_streams = 1;
 
+	/* Get possile USB 3.0 type PHY (PIPE3) available with xhci */
+	xhci->shared_hcd->gen_phy = devm_phy_get(&pdev->dev, "usb3-phy");
+	if (IS_ERR(xhci->shared_hcd->gen_phy)) {
+		ret = PTR_ERR(xhci->shared_hcd->gen_phy);
+		if (ret == -EPROBE_DEFER)
+			return ret;
+		else if (ret != -ENOSYS && ret != -ENODEV)
+			dev_warn(&pdev->dev,
+				 "Error retrieving usb3 phy: %d\n", ret);
+	}
+
 	ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
 	if (ret)
 		goto put_usb3_hcd;
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v5 3/4] usb: hcd: Caibrate PHY post hcd reset
  2014-08-21 14:55 [PATCH v5 0/4] Fine tune USB 3.0 PHY on exynos5420 Vivek Gautam
  2014-08-21 14:55 ` [PATCH v5 1/4] phy: Add provision for calibrating phy Vivek Gautam
  2014-08-21 14:55 ` [PATCH v5 2/4] usb: host: xhci-plat: Get PHYs for xhci's hcds Vivek Gautam
@ 2014-08-21 14:55 ` Vivek Gautam
  2014-08-22 10:49   ` Andreas Färber
  2014-08-21 14:55 ` [PATCH v5 4/4] phy: exynos5-usbdrd: Calibrate LOS levels for exynos5420/5800 Vivek Gautam
  3 siblings, 1 reply; 12+ messages in thread
From: Vivek Gautam @ 2014-08-21 14:55 UTC (permalink / raw)
  To: linux-usb
  Cc: linux-samsung-soc, linux-kernel, gregkh, kishon, kgene.kim,
	mathias.nyman, stern, sergei.shtylyov, heikki.krogerus, balbi,
	Vivek Gautam

Some quirky PHYs may require to be calibrated post the
hcd initialization.
The USB 3.0 DRD PHY on Exynos5420/5800 systems, coming along
with Synopsys's DWC3 controller, is one such PHY which needs
to be calibrated post xhci's reset at initialization time and
at resume time, to get the controller work at SuperSpeed.
So facilitating the HCDs to calibrate the PHY.

Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
---
 drivers/usb/core/hcd.c |   22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index c4ed66c..a42b448 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2202,6 +2202,7 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
 	struct usb_hcd	*hcd = container_of(rhdev->bus, struct usb_hcd, self);
 	int		status;
 	int		old_state = hcd->state;
+	int		ret;
 
 	dev_dbg(&rhdev->dev, "usb %sresume\n",
 			(PMSG_IS_AUTO(msg) ? "auto-" : ""));
@@ -2216,6 +2217,17 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
 
 	hcd->state = HC_STATE_RESUMING;
 	status = hcd->driver->bus_resume(hcd);
+
+	/* calibrate the phy here */
+	if (!IS_ERR(hcd->gen_phy)) {
+		ret = phy_calibrate(hcd->gen_phy);
+		if (ret < 0 && ret != -ENOTSUPP) {
+			dev_err(hcd->self.controller,
+				"failed to calibrate USB PHY\n");
+			return ret;
+		}
+	}
+
 	clear_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags);
 	if (status == 0) {
 		struct usb_device *udev;
@@ -2738,6 +2750,16 @@ int usb_add_hcd(struct usb_hcd *hcd,
 	}
 	hcd->rh_pollable = 1;
 
+	/* calibrate the phy here */
+	if (!IS_ERR(hcd->gen_phy)) {
+		retval = phy_calibrate(hcd->gen_phy);
+		if (retval < 0 && retval != -ENOTSUPP) {
+			dev_err(hcd->self.controller,
+				"failed to calibrate USB PHY\n");
+			return retval;
+		}
+	}
+
 	/* NOTE: root hub and controller capabilities may not be the same */
 	if (device_can_wakeup(hcd->self.controller)
 			&& device_can_wakeup(&hcd->self.root_hub->dev))
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v5 4/4] phy: exynos5-usbdrd: Calibrate LOS levels for exynos5420/5800
  2014-08-21 14:55 [PATCH v5 0/4] Fine tune USB 3.0 PHY on exynos5420 Vivek Gautam
                   ` (2 preceding siblings ...)
  2014-08-21 14:55 ` [PATCH v5 3/4] usb: hcd: Caibrate PHY post hcd reset Vivek Gautam
@ 2014-08-21 14:55 ` Vivek Gautam
  2014-08-27  1:58     ` Jingoo Han
  3 siblings, 1 reply; 12+ messages in thread
From: Vivek Gautam @ 2014-08-21 14:55 UTC (permalink / raw)
  To: linux-usb
  Cc: linux-samsung-soc, linux-kernel, gregkh, kishon, kgene.kim,
	mathias.nyman, stern, sergei.shtylyov, heikki.krogerus, balbi,
	Vivek Gautam

Adding phy calibrate callback, which facilitates setting certain
PHY settings post initialization of the PHY controller.
Exynos5420 and Exynos5800 have 28nm USB 3.0 DRD PHY for which
the Loss-of-Signal (LOS) Detector Threshold Level as well as
Tx-Vboost-Level should be controlled for Super-Speed operations.

Additionally set proper time to wait for RxDetect measurement,
for desired PHY reference clock, so as to solve issue with enumeration
of few USB 3.0 devices, like Samsung SUM-TSB16S 3.0 USB drive
on the controller.
We are using CR_port for this purpose to send required data
to override the LOS values.

On testing with USB 3.0 devices on USB 3.0 port present on
SMDK5420, and peach-pit boards should see following message:
usb 2-1: new SuperSpeed USB device number 2 using xhci-hcd

and without this patch, should see below shown message:
usb 1-1: new high-speed USB device number 2 using xhci-hcd

Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
---
 drivers/phy/phy-exynos5-usbdrd.c |  169 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 169 insertions(+)

diff --git a/drivers/phy/phy-exynos5-usbdrd.c b/drivers/phy/phy-exynos5-usbdrd.c
index 47f47fe..fa13784 100644
--- a/drivers/phy/phy-exynos5-usbdrd.c
+++ b/drivers/phy/phy-exynos5-usbdrd.c
@@ -89,8 +89,20 @@
 #define PHYCLKRST_COMMONONN			BIT(0)
 
 #define EXYNOS5_DRD_PHYREG0			0x14
+
+#define EXYNOS5_DRD_PHYREG0_SSC_REF_CLK_SEL	BIT(21)
+#define EXYNOS5_DRD_PHYREG0_SSC_RANGE		BIT(20)
+#define EXYNOS5_DRD_PHYREG0_CR_WRITE		BIT(19)
+#define EXYNOS5_DRD_PHYREG0_CR_READ		BIT(18)
+#define EXYNOS5_DRD_PHYREG0_CR_DATA_IN(_x)	((_x) << 2)
+#define EXYNOS5_DRD_PHYREG0_CR_CAP_DATA		BIT(1)
+#define EXYNOS5_DRD_PHYREG0_CR_CAP_ADDR		BIT(0)
+
 #define EXYNOS5_DRD_PHYREG1			0x18
 
+#define EXYNOS5_DRD_PHYREG1_CR_DATA_OUT(_x)	((_x) << 1)
+#define EXYNOS5_DRD_PHYREG1_CR_ACK		BIT(0)
+
 #define EXYNOS5_DRD_PHYPARAM0			0x1c
 
 #define PHYPARAM0_REF_USE_PAD			BIT(31)
@@ -118,6 +130,26 @@
 #define EXYNOS5_DRD_PHYRESUME			0x34
 #define EXYNOS5_DRD_LINKPORT			0x44
 
+/* USB 3.0 DRD PHY SS Function Control Reg; accessed by CR_PORT */
+#define EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN		(0x15)
+
+#define LOSLEVEL_OVRD_IN_LOS_BIAS_5420			(0x5 << 13)
+#define LOSLEVEL_OVRD_IN_LOS_BIAS_DEFAULT		(0x0 << 13)
+#define LOSLEVEL_OVRD_IN_EN				(0x1 << 10)
+#define LOSLEVEL_OVRD_IN_LOS_LEVEL_DEFAULT		(0x9 << 0)
+
+#define EXYNOS5_DRD_PHYSS_TX_VBOOSTLEVEL_OVRD_IN	(0x12)
+#define TX_VBOOSTLEVEL_OVRD_IN_VBOOST_5420		(0x5 << 13)
+#define TX_VBOOSTLEVEL_OVRD_IN_VBOOST_DEFAULT		(0x4 << 13)
+
+#define EXYNOS5_DRD_PHYSS_LANE0_TX_DEBUG		(0x1010)
+#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_19M2_20M		(0x4 << 4)
+#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_24M		(0x8 << 4)
+#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_25M_26M		(0x8 << 4)
+#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_48M_50M_52M	(0x20 << 4)
+#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_62M5		(0x20 << 4)
+#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_96M_100M		(0x40 << 4)
+
 #define KHZ	1000
 #define MHZ	(KHZ * KHZ)
 
@@ -135,12 +167,14 @@ struct exynos5_usbdrd_phy_config {
 	void (*phy_isol)(struct phy_usb_instance *inst, u32 on);
 	void (*phy_init)(struct exynos5_usbdrd_phy *phy_drd);
 	unsigned int (*set_refclk)(struct phy_usb_instance *inst);
+	int (*phy_calibrate)(struct phy_usb_instance *inst);
 };
 
 struct exynos5_usbdrd_phy_drvdata {
 	const struct exynos5_usbdrd_phy_config *phy_cfg;
 	u32 pmu_offset_usbdrd0_phy;
 	u32 pmu_offset_usbdrd1_phy;
+	void (*calibrate)(struct exynos5_usbdrd_phy *phy_drd);
 };
 
 /**
@@ -487,6 +521,138 @@ static int exynos5_usbdrd_phy_power_off(struct phy *phy)
 	return 0;
 }
 
+static void crport_handshake(struct exynos5_usbdrd_phy *phy_drd,
+						u32 val, u32 cmd)
+{
+	u32 usec = 100;
+	u32 result;
+
+	writel(val | cmd, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
+
+	do {
+		result = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1);
+		if (result & EXYNOS5_DRD_PHYREG1_CR_ACK)
+			break;
+
+		udelay(1);
+	} while (usec-- > 0);
+
+	if (!usec)
+		dev_err(phy_drd->dev,
+			"CRPORT handshake timeout1 (0x%08x)\n", val);
+
+	usec = 100;
+
+	writel(val, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
+
+	do {
+		result = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1);
+		if (!(result & EXYNOS5_DRD_PHYREG1_CR_ACK))
+			break;
+
+		udelay(1);
+	} while (usec-- > 0);
+
+	if (!usec)
+		dev_err(phy_drd->dev,
+			"CRPORT handshake timeout2 (0x%08x)\n", val);
+}
+
+static void crport_ctrl_write(struct exynos5_usbdrd_phy *phy_drd,
+						u32 addr, u32 data)
+{
+	/* Write Address */
+	crport_handshake(phy_drd, EXYNOS5_DRD_PHYREG0_CR_DATA_IN(addr),
+			 EXYNOS5_DRD_PHYREG0_CR_CAP_ADDR);
+
+	/* Write Data */
+	crport_handshake(phy_drd, EXYNOS5_DRD_PHYREG0_CR_DATA_IN(data),
+			 EXYNOS5_DRD_PHYREG0_CR_CAP_DATA);
+	crport_handshake(phy_drd, EXYNOS5_DRD_PHYREG0_CR_DATA_IN(data),
+			 EXYNOS5_DRD_PHYREG0_CR_WRITE);
+}
+
+/*
+ * Override PHY paramaeters using CR_PORT register to calibrate settings
+ * to meet meet SuperSpeed requirements, on Exynos5420 and Exynos5800 systems,
+ * which have 28nm USB 3.0 DRD PHY.
+ */
+static void exynos5420_usbdrd_phy_calibrate(struct exynos5_usbdrd_phy *phy_drd)
+{
+	u32 temp;
+
+	/*
+	 * Change los_bias to (0x5) for 28nm PHY from a
+	 * default value (0x0); los_level is set as default
+	 * (0x9) as also reflected in los_level[30:26] bits
+	 * of PHYPARAM0 register.
+	 */
+	temp = LOSLEVEL_OVRD_IN_LOS_BIAS_5420 |
+		LOSLEVEL_OVRD_IN_EN |
+		LOSLEVEL_OVRD_IN_LOS_LEVEL_DEFAULT;
+	crport_ctrl_write(phy_drd,
+			  EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN,
+			  temp);
+
+	/*
+	 * Set tx_vboost_lvl to (0x5) for 28nm PHY Tuning,
+	 * to raise Tx signal level from its default value of (0x4)
+	 */
+	temp = TX_VBOOSTLEVEL_OVRD_IN_VBOOST_5420;
+	crport_ctrl_write(phy_drd,
+			  EXYNOS5_DRD_PHYSS_TX_VBOOSTLEVEL_OVRD_IN,
+			  temp);
+
+	/*
+	 * Set proper time to wait for RxDetect measurement, for
+	 * desired reference clock of PHY, by tuning the CRPORT
+	 * register LANE0.TX_DEBUG which is internal to PHY.
+	 * This fixes issue with few USB 3.0 devices, which are
+	 * not detected (not even generate interrupts on the bus
+	 * on insertion) without this change.
+	 * e.g. Samsung SUM-TSB16S 3.0 USB drive.
+	 */
+	switch (phy_drd->extrefclk) {
+	case EXYNOS5_FSEL_50MHZ:
+		temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_48M_50M_52M;
+		break;
+	case EXYNOS5_FSEL_20MHZ:
+	case EXYNOS5_FSEL_19MHZ2:
+		temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_19M2_20M;
+		break;
+	case EXYNOS5_FSEL_24MHZ:
+	default:
+		temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_24M;
+		break;
+	}
+
+	crport_ctrl_write(phy_drd,
+			  EXYNOS5_DRD_PHYSS_LANE0_TX_DEBUG,
+			  temp);
+}
+
+/* Calibrate PIPE3 PHY settings, if any */
+static int exynos5_usbdrd_pipe3_calibrate(struct phy_usb_instance *inst)
+{
+	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
+
+	/* Call respective phy_calibrate given by certain platform */
+	if (phy_drd->drv_data->calibrate)
+		phy_drd->drv_data->calibrate(phy_drd);
+
+	return 0;
+}
+
+static int exynos5_usbdrd_phy_calibrate(struct phy *phy)
+{
+	struct phy_usb_instance *inst = phy_get_drvdata(phy);
+
+	if (inst->phy_cfg->phy_calibrate)
+		inst->phy_cfg->phy_calibrate(inst);
+
+	return 0;
+}
+
 static struct phy *exynos5_usbdrd_phy_xlate(struct device *dev,
 					struct of_phandle_args *args)
 {
@@ -503,6 +669,7 @@ static struct phy_ops exynos5_usbdrd_phy_ops = {
 	.exit		= exynos5_usbdrd_phy_exit,
 	.power_on	= exynos5_usbdrd_phy_power_on,
 	.power_off	= exynos5_usbdrd_phy_power_off,
+	.calibrate	= exynos5_usbdrd_phy_calibrate,
 	.owner		= THIS_MODULE,
 };
 
@@ -518,6 +685,7 @@ static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
 		.phy_isol	= exynos5_usbdrd_phy_isol,
 		.phy_init	= exynos5_usbdrd_pipe3_init,
 		.set_refclk	= exynos5_usbdrd_pipe3_set_refclk,
+		.phy_calibrate	= exynos5_usbdrd_pipe3_calibrate,
 	},
 };
 
@@ -525,6 +693,7 @@ static const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = {
 	.phy_cfg		= phy_cfg_exynos5,
 	.pmu_offset_usbdrd0_phy	= EXYNOS5_USBDRD_PHY_CONTROL,
 	.pmu_offset_usbdrd1_phy	= EXYNOS5420_USBDRD1_PHY_CONTROL,
+	.calibrate		= exynos5420_usbdrd_phy_calibrate,
 };
 
 static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = {
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH v5 3/4] usb: hcd: Caibrate PHY post hcd reset
  2014-08-21 14:55 ` [PATCH v5 3/4] usb: hcd: Caibrate PHY post hcd reset Vivek Gautam
@ 2014-08-22 10:49   ` Andreas Färber
  2014-08-28  4:09       ` Vivek Gautam
  0 siblings, 1 reply; 12+ messages in thread
From: Andreas Färber @ 2014-08-22 10:49 UTC (permalink / raw)
  To: Vivek Gautam, linux-usb
  Cc: linux-samsung-soc, linux-kernel, gregkh, kishon, kgene.kim,
	mathias.nyman, stern, sergei.shtylyov, heikki.krogerus, balbi

Hi,

s/Caibrate/Calibrate/

Cheers,
Andreas

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v5 4/4] phy: exynos5-usbdrd: Calibrate LOS levels for exynos5420/5800
@ 2014-08-27  1:58     ` Jingoo Han
  0 siblings, 0 replies; 12+ messages in thread
From: Jingoo Han @ 2014-08-27  1:58 UTC (permalink / raw)
  To: 'Vivek Gautam', linux-usb
  Cc: linux-samsung-soc, linux-kernel, gregkh, kishon, kgene.kim,
	mathias.nyman, stern, sergei.shtylyov, heikki.krogerus, balbi,
	'Jingoo Han'

On Thursday, August 21, 2014 11:55 PM, Vivek Gautam wrote:
> 
> Adding phy calibrate callback, which facilitates setting certain
> PHY settings post initialization of the PHY controller.
> Exynos5420 and Exynos5800 have 28nm USB 3.0 DRD PHY for which
> the Loss-of-Signal (LOS) Detector Threshold Level as well as
> Tx-Vboost-Level should be controlled for Super-Speed operations.
> 
> Additionally set proper time to wait for RxDetect measurement,
> for desired PHY reference clock, so as to solve issue with enumeration
> of few USB 3.0 devices, like Samsung SUM-TSB16S 3.0 USB drive
> on the controller.
> We are using CR_port for this purpose to send required data
> to override the LOS values.
> 
> On testing with USB 3.0 devices on USB 3.0 port present on
> SMDK5420, and peach-pit boards should see following message:
> usb 2-1: new SuperSpeed USB device number 2 using xhci-hcd
> 
> and without this patch, should see below shown message:
> usb 1-1: new high-speed USB device number 2 using xhci-hcd
> 
> Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
> ---
>  drivers/phy/phy-exynos5-usbdrd.c |  169 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 169 insertions(+)
> 
> diff --git a/drivers/phy/phy-exynos5-usbdrd.c b/drivers/phy/phy-exynos5-usbdrd.c
> index 47f47fe..fa13784 100644
> --- a/drivers/phy/phy-exynos5-usbdrd.c
> +++ b/drivers/phy/phy-exynos5-usbdrd.c
> @@ -89,8 +89,20 @@
>  #define PHYCLKRST_COMMONONN			BIT(0)
> 
>  #define EXYNOS5_DRD_PHYREG0			0x14
> +
> +#define EXYNOS5_DRD_PHYREG0_SSC_REF_CLK_SEL	BIT(21)
> +#define EXYNOS5_DRD_PHYREG0_SSC_RANGE		BIT(20)
> +#define EXYNOS5_DRD_PHYREG0_CR_WRITE		BIT(19)
> +#define EXYNOS5_DRD_PHYREG0_CR_READ		BIT(18)
> +#define EXYNOS5_DRD_PHYREG0_CR_DATA_IN(_x)	((_x) << 2)
> +#define EXYNOS5_DRD_PHYREG0_CR_CAP_DATA		BIT(1)
> +#define EXYNOS5_DRD_PHYREG0_CR_CAP_ADDR		BIT(0)
> +
>  #define EXYNOS5_DRD_PHYREG1			0x18
> 
> +#define EXYNOS5_DRD_PHYREG1_CR_DATA_OUT(_x)	((_x) << 1)
> +#define EXYNOS5_DRD_PHYREG1_CR_ACK		BIT(0)
> +
>  #define EXYNOS5_DRD_PHYPARAM0			0x1c
> 
>  #define PHYPARAM0_REF_USE_PAD			BIT(31)
> @@ -118,6 +130,26 @@
>  #define EXYNOS5_DRD_PHYRESUME			0x34
>  #define EXYNOS5_DRD_LINKPORT			0x44
> 
> +/* USB 3.0 DRD PHY SS Function Control Reg; accessed by CR_PORT */
> +#define EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN		(0x15)
> +

Please remove unnecessary line.

> +#define LOSLEVEL_OVRD_IN_LOS_BIAS_5420			(0x5 << 13)
> +#define LOSLEVEL_OVRD_IN_LOS_BIAS_DEFAULT		(0x0 << 13)
> +#define LOSLEVEL_OVRD_IN_EN				(0x1 << 10)
> +#define LOSLEVEL_OVRD_IN_LOS_LEVEL_DEFAULT		(0x9 << 0)
> +
> +#define EXYNOS5_DRD_PHYSS_TX_VBOOSTLEVEL_OVRD_IN	(0x12)
> +#define TX_VBOOSTLEVEL_OVRD_IN_VBOOST_5420		(0x5 << 13)
> +#define TX_VBOOSTLEVEL_OVRD_IN_VBOOST_DEFAULT		(0x4 << 13)
> +
> +#define EXYNOS5_DRD_PHYSS_LANE0_TX_DEBUG		(0x1010)
> +#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_19M2_20M		(0x4 << 4)
> +#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_24M		(0x8 << 4)
> +#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_25M_26M		(0x8 << 4)
> +#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_48M_50M_52M	(0x20 << 4)
> +#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_62M5		(0x20 << 4)
> +#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_96M_100M		(0x40 << 4)
> +
>  #define KHZ	1000
>  #define MHZ	(KHZ * KHZ)
> 
> @@ -135,12 +167,14 @@ struct exynos5_usbdrd_phy_config {
>  	void (*phy_isol)(struct phy_usb_instance *inst, u32 on);
>  	void (*phy_init)(struct exynos5_usbdrd_phy *phy_drd);
>  	unsigned int (*set_refclk)(struct phy_usb_instance *inst);
> +	int (*phy_calibrate)(struct phy_usb_instance *inst);
>  };
> 
>  struct exynos5_usbdrd_phy_drvdata {
>  	const struct exynos5_usbdrd_phy_config *phy_cfg;
>  	u32 pmu_offset_usbdrd0_phy;
>  	u32 pmu_offset_usbdrd1_phy;
> +	void (*calibrate)(struct exynos5_usbdrd_phy *phy_drd);
>  };
> 
>  /**
> @@ -487,6 +521,138 @@ static int exynos5_usbdrd_phy_power_off(struct phy *phy)
>  	return 0;
>  }
> 
> +static void crport_handshake(struct exynos5_usbdrd_phy *phy_drd,
> +						u32 val, u32 cmd)
> +{
> +	u32 usec = 100;
> +	u32 result;
> +
> +	writel(val | cmd, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
> +
> +	do {
> +		result = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1);
> +		if (result & EXYNOS5_DRD_PHYREG1_CR_ACK)
> +			break;
> +
> +		udelay(1);
> +	} while (usec-- > 0);
> +
> +	if (!usec)
> +		dev_err(phy_drd->dev,
> +			"CRPORT handshake timeout1 (0x%08x)\n", val);
> +
> +	usec = 100;
> +
> +	writel(val, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
> +
> +	do {
> +		result = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1);
> +		if (!(result & EXYNOS5_DRD_PHYREG1_CR_ACK))
> +			break;
> +
> +		udelay(1);
> +	} while (usec-- > 0);
> +
> +	if (!usec)
> +		dev_err(phy_drd->dev,
> +			"CRPORT handshake timeout2 (0x%08x)\n", val);
> +}
> +
> +static void crport_ctrl_write(struct exynos5_usbdrd_phy *phy_drd,
> +						u32 addr, u32 data)
> +{
> +	/* Write Address */
> +	crport_handshake(phy_drd, EXYNOS5_DRD_PHYREG0_CR_DATA_IN(addr),
> +			 EXYNOS5_DRD_PHYREG0_CR_CAP_ADDR);

According to the guidance from H/W team, before calling crport_handshake(),
write access for EXYNOS5_DRD_PHYREG0 register is necessary.

Please, add the write access as follows.

+	/* Write Address */
+	writel(EXYNOS5_DRD_PHYREG0_CR_DATA_IN(addr),
+		phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
+	crport_handshake(phy_drd, EXYNOS5_DRD_PHYREG0_CR_DATA_IN(addr),
+			 EXYNOS5_DRD_PHYREG0_CR_CAP_ADDR);

Best regards,
Jingoo Han

> +
> +	/* Write Data */
> +	crport_handshake(phy_drd, EXYNOS5_DRD_PHYREG0_CR_DATA_IN(data),
> +			 EXYNOS5_DRD_PHYREG0_CR_CAP_DATA);
> +	crport_handshake(phy_drd, EXYNOS5_DRD_PHYREG0_CR_DATA_IN(data),
> +			 EXYNOS5_DRD_PHYREG0_CR_WRITE);
> +}
> +
> +/*
> + * Override PHY paramaeters using CR_PORT register to calibrate settings
> + * to meet meet SuperSpeed requirements, on Exynos5420 and Exynos5800 systems,
> + * which have 28nm USB 3.0 DRD PHY.
> + */
> +static void exynos5420_usbdrd_phy_calibrate(struct exynos5_usbdrd_phy *phy_drd)
> +{
> +	u32 temp;
> +
> +	/*
> +	 * Change los_bias to (0x5) for 28nm PHY from a
> +	 * default value (0x0); los_level is set as default
> +	 * (0x9) as also reflected in los_level[30:26] bits
> +	 * of PHYPARAM0 register.
> +	 */
> +	temp = LOSLEVEL_OVRD_IN_LOS_BIAS_5420 |
> +		LOSLEVEL_OVRD_IN_EN |
> +		LOSLEVEL_OVRD_IN_LOS_LEVEL_DEFAULT;
> +	crport_ctrl_write(phy_drd,
> +			  EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN,
> +			  temp);
> +
> +	/*
> +	 * Set tx_vboost_lvl to (0x5) for 28nm PHY Tuning,
> +	 * to raise Tx signal level from its default value of (0x4)
> +	 */
> +	temp = TX_VBOOSTLEVEL_OVRD_IN_VBOOST_5420;
> +	crport_ctrl_write(phy_drd,
> +			  EXYNOS5_DRD_PHYSS_TX_VBOOSTLEVEL_OVRD_IN,
> +			  temp);
> +
> +	/*
> +	 * Set proper time to wait for RxDetect measurement, for
> +	 * desired reference clock of PHY, by tuning the CRPORT
> +	 * register LANE0.TX_DEBUG which is internal to PHY.
> +	 * This fixes issue with few USB 3.0 devices, which are
> +	 * not detected (not even generate interrupts on the bus
> +	 * on insertion) without this change.
> +	 * e.g. Samsung SUM-TSB16S 3.0 USB drive.
> +	 */
> +	switch (phy_drd->extrefclk) {
> +	case EXYNOS5_FSEL_50MHZ:
> +		temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_48M_50M_52M;
> +		break;
> +	case EXYNOS5_FSEL_20MHZ:
> +	case EXYNOS5_FSEL_19MHZ2:
> +		temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_19M2_20M;
> +		break;
> +	case EXYNOS5_FSEL_24MHZ:
> +	default:
> +		temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_24M;
> +		break;
> +	}
> +
> +	crport_ctrl_write(phy_drd,
> +			  EXYNOS5_DRD_PHYSS_LANE0_TX_DEBUG,
> +			  temp);
> +}
> +
> +/* Calibrate PIPE3 PHY settings, if any */
> +static int exynos5_usbdrd_pipe3_calibrate(struct phy_usb_instance *inst)
> +{
> +	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
> +
> +	/* Call respective phy_calibrate given by certain platform */
> +	if (phy_drd->drv_data->calibrate)
> +		phy_drd->drv_data->calibrate(phy_drd);
> +
> +	return 0;
> +}
> +
> +static int exynos5_usbdrd_phy_calibrate(struct phy *phy)
> +{
> +	struct phy_usb_instance *inst = phy_get_drvdata(phy);
> +
> +	if (inst->phy_cfg->phy_calibrate)
> +		inst->phy_cfg->phy_calibrate(inst);
> +
> +	return 0;
> +}
> +
>  static struct phy *exynos5_usbdrd_phy_xlate(struct device *dev,
>  					struct of_phandle_args *args)
>  {
> @@ -503,6 +669,7 @@ static struct phy_ops exynos5_usbdrd_phy_ops = {
>  	.exit		= exynos5_usbdrd_phy_exit,
>  	.power_on	= exynos5_usbdrd_phy_power_on,
>  	.power_off	= exynos5_usbdrd_phy_power_off,
> +	.calibrate	= exynos5_usbdrd_phy_calibrate,
>  	.owner		= THIS_MODULE,
>  };
> 
> @@ -518,6 +685,7 @@ static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
>  		.phy_isol	= exynos5_usbdrd_phy_isol,
>  		.phy_init	= exynos5_usbdrd_pipe3_init,
>  		.set_refclk	= exynos5_usbdrd_pipe3_set_refclk,
> +		.phy_calibrate	= exynos5_usbdrd_pipe3_calibrate,
>  	},
>  };
> 
> @@ -525,6 +693,7 @@ static const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = {
>  	.phy_cfg		= phy_cfg_exynos5,
>  	.pmu_offset_usbdrd0_phy	= EXYNOS5_USBDRD_PHY_CONTROL,
>  	.pmu_offset_usbdrd1_phy	= EXYNOS5420_USBDRD1_PHY_CONTROL,
> +	.calibrate		= exynos5420_usbdrd_phy_calibrate,

Hmm, how about adding just flag for this, instead of function callback?
It looks a little bit confusing.

Best regards,
Jingoo Han

>  };
> 
>  static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = {
> --
> 1.7.10.4
> 


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v5 4/4] phy: exynos5-usbdrd: Calibrate LOS levels for exynos5420/5800
@ 2014-08-27  1:58     ` Jingoo Han
  0 siblings, 0 replies; 12+ messages in thread
From: Jingoo Han @ 2014-08-27  1:58 UTC (permalink / raw)
  To: 'Vivek Gautam', linux-usb-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, kishon-l0cyMroinI0,
	kgene.kim-Sze3O3UU22JBDgjK7y7TUQ,
	mathias.nyman-ral2JQCrhuEAvxtiuMwx3w,
	stern-nwvwT67g6+6dFdvTe/nMLpVzexx5G7lz,
	sergei.shtylyov-M4DtvfQ/ZS1MRgGoP+s0PdBPR1lH4CV8,
	heikki.krogerus-VuQAYsv1563Yd54FQh9/CA, balbi-l0cyMroinI0,
	'Jingoo Han'

On Thursday, August 21, 2014 11:55 PM, Vivek Gautam wrote:
> 
> Adding phy calibrate callback, which facilitates setting certain
> PHY settings post initialization of the PHY controller.
> Exynos5420 and Exynos5800 have 28nm USB 3.0 DRD PHY for which
> the Loss-of-Signal (LOS) Detector Threshold Level as well as
> Tx-Vboost-Level should be controlled for Super-Speed operations.
> 
> Additionally set proper time to wait for RxDetect measurement,
> for desired PHY reference clock, so as to solve issue with enumeration
> of few USB 3.0 devices, like Samsung SUM-TSB16S 3.0 USB drive
> on the controller.
> We are using CR_port for this purpose to send required data
> to override the LOS values.
> 
> On testing with USB 3.0 devices on USB 3.0 port present on
> SMDK5420, and peach-pit boards should see following message:
> usb 2-1: new SuperSpeed USB device number 2 using xhci-hcd
> 
> and without this patch, should see below shown message:
> usb 1-1: new high-speed USB device number 2 using xhci-hcd
> 
> Signed-off-by: Vivek Gautam <gautam.vivek-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
> ---
>  drivers/phy/phy-exynos5-usbdrd.c |  169 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 169 insertions(+)
> 
> diff --git a/drivers/phy/phy-exynos5-usbdrd.c b/drivers/phy/phy-exynos5-usbdrd.c
> index 47f47fe..fa13784 100644
> --- a/drivers/phy/phy-exynos5-usbdrd.c
> +++ b/drivers/phy/phy-exynos5-usbdrd.c
> @@ -89,8 +89,20 @@
>  #define PHYCLKRST_COMMONONN			BIT(0)
> 
>  #define EXYNOS5_DRD_PHYREG0			0x14
> +
> +#define EXYNOS5_DRD_PHYREG0_SSC_REF_CLK_SEL	BIT(21)
> +#define EXYNOS5_DRD_PHYREG0_SSC_RANGE		BIT(20)
> +#define EXYNOS5_DRD_PHYREG0_CR_WRITE		BIT(19)
> +#define EXYNOS5_DRD_PHYREG0_CR_READ		BIT(18)
> +#define EXYNOS5_DRD_PHYREG0_CR_DATA_IN(_x)	((_x) << 2)
> +#define EXYNOS5_DRD_PHYREG0_CR_CAP_DATA		BIT(1)
> +#define EXYNOS5_DRD_PHYREG0_CR_CAP_ADDR		BIT(0)
> +
>  #define EXYNOS5_DRD_PHYREG1			0x18
> 
> +#define EXYNOS5_DRD_PHYREG1_CR_DATA_OUT(_x)	((_x) << 1)
> +#define EXYNOS5_DRD_PHYREG1_CR_ACK		BIT(0)
> +
>  #define EXYNOS5_DRD_PHYPARAM0			0x1c
> 
>  #define PHYPARAM0_REF_USE_PAD			BIT(31)
> @@ -118,6 +130,26 @@
>  #define EXYNOS5_DRD_PHYRESUME			0x34
>  #define EXYNOS5_DRD_LINKPORT			0x44
> 
> +/* USB 3.0 DRD PHY SS Function Control Reg; accessed by CR_PORT */
> +#define EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN		(0x15)
> +

Please remove unnecessary line.

> +#define LOSLEVEL_OVRD_IN_LOS_BIAS_5420			(0x5 << 13)
> +#define LOSLEVEL_OVRD_IN_LOS_BIAS_DEFAULT		(0x0 << 13)
> +#define LOSLEVEL_OVRD_IN_EN				(0x1 << 10)
> +#define LOSLEVEL_OVRD_IN_LOS_LEVEL_DEFAULT		(0x9 << 0)
> +
> +#define EXYNOS5_DRD_PHYSS_TX_VBOOSTLEVEL_OVRD_IN	(0x12)
> +#define TX_VBOOSTLEVEL_OVRD_IN_VBOOST_5420		(0x5 << 13)
> +#define TX_VBOOSTLEVEL_OVRD_IN_VBOOST_DEFAULT		(0x4 << 13)
> +
> +#define EXYNOS5_DRD_PHYSS_LANE0_TX_DEBUG		(0x1010)
> +#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_19M2_20M		(0x4 << 4)
> +#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_24M		(0x8 << 4)
> +#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_25M_26M		(0x8 << 4)
> +#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_48M_50M_52M	(0x20 << 4)
> +#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_62M5		(0x20 << 4)
> +#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_96M_100M		(0x40 << 4)
> +
>  #define KHZ	1000
>  #define MHZ	(KHZ * KHZ)
> 
> @@ -135,12 +167,14 @@ struct exynos5_usbdrd_phy_config {
>  	void (*phy_isol)(struct phy_usb_instance *inst, u32 on);
>  	void (*phy_init)(struct exynos5_usbdrd_phy *phy_drd);
>  	unsigned int (*set_refclk)(struct phy_usb_instance *inst);
> +	int (*phy_calibrate)(struct phy_usb_instance *inst);
>  };
> 
>  struct exynos5_usbdrd_phy_drvdata {
>  	const struct exynos5_usbdrd_phy_config *phy_cfg;
>  	u32 pmu_offset_usbdrd0_phy;
>  	u32 pmu_offset_usbdrd1_phy;
> +	void (*calibrate)(struct exynos5_usbdrd_phy *phy_drd);
>  };
> 
>  /**
> @@ -487,6 +521,138 @@ static int exynos5_usbdrd_phy_power_off(struct phy *phy)
>  	return 0;
>  }
> 
> +static void crport_handshake(struct exynos5_usbdrd_phy *phy_drd,
> +						u32 val, u32 cmd)
> +{
> +	u32 usec = 100;
> +	u32 result;
> +
> +	writel(val | cmd, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
> +
> +	do {
> +		result = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1);
> +		if (result & EXYNOS5_DRD_PHYREG1_CR_ACK)
> +			break;
> +
> +		udelay(1);
> +	} while (usec-- > 0);
> +
> +	if (!usec)
> +		dev_err(phy_drd->dev,
> +			"CRPORT handshake timeout1 (0x%08x)\n", val);
> +
> +	usec = 100;
> +
> +	writel(val, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
> +
> +	do {
> +		result = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1);
> +		if (!(result & EXYNOS5_DRD_PHYREG1_CR_ACK))
> +			break;
> +
> +		udelay(1);
> +	} while (usec-- > 0);
> +
> +	if (!usec)
> +		dev_err(phy_drd->dev,
> +			"CRPORT handshake timeout2 (0x%08x)\n", val);
> +}
> +
> +static void crport_ctrl_write(struct exynos5_usbdrd_phy *phy_drd,
> +						u32 addr, u32 data)
> +{
> +	/* Write Address */
> +	crport_handshake(phy_drd, EXYNOS5_DRD_PHYREG0_CR_DATA_IN(addr),
> +			 EXYNOS5_DRD_PHYREG0_CR_CAP_ADDR);

According to the guidance from H/W team, before calling crport_handshake(),
write access for EXYNOS5_DRD_PHYREG0 register is necessary.

Please, add the write access as follows.

+	/* Write Address */
+	writel(EXYNOS5_DRD_PHYREG0_CR_DATA_IN(addr),
+		phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
+	crport_handshake(phy_drd, EXYNOS5_DRD_PHYREG0_CR_DATA_IN(addr),
+			 EXYNOS5_DRD_PHYREG0_CR_CAP_ADDR);

Best regards,
Jingoo Han

> +
> +	/* Write Data */
> +	crport_handshake(phy_drd, EXYNOS5_DRD_PHYREG0_CR_DATA_IN(data),
> +			 EXYNOS5_DRD_PHYREG0_CR_CAP_DATA);
> +	crport_handshake(phy_drd, EXYNOS5_DRD_PHYREG0_CR_DATA_IN(data),
> +			 EXYNOS5_DRD_PHYREG0_CR_WRITE);
> +}
> +
> +/*
> + * Override PHY paramaeters using CR_PORT register to calibrate settings
> + * to meet meet SuperSpeed requirements, on Exynos5420 and Exynos5800 systems,
> + * which have 28nm USB 3.0 DRD PHY.
> + */
> +static void exynos5420_usbdrd_phy_calibrate(struct exynos5_usbdrd_phy *phy_drd)
> +{
> +	u32 temp;
> +
> +	/*
> +	 * Change los_bias to (0x5) for 28nm PHY from a
> +	 * default value (0x0); los_level is set as default
> +	 * (0x9) as also reflected in los_level[30:26] bits
> +	 * of PHYPARAM0 register.
> +	 */
> +	temp = LOSLEVEL_OVRD_IN_LOS_BIAS_5420 |
> +		LOSLEVEL_OVRD_IN_EN |
> +		LOSLEVEL_OVRD_IN_LOS_LEVEL_DEFAULT;
> +	crport_ctrl_write(phy_drd,
> +			  EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN,
> +			  temp);
> +
> +	/*
> +	 * Set tx_vboost_lvl to (0x5) for 28nm PHY Tuning,
> +	 * to raise Tx signal level from its default value of (0x4)
> +	 */
> +	temp = TX_VBOOSTLEVEL_OVRD_IN_VBOOST_5420;
> +	crport_ctrl_write(phy_drd,
> +			  EXYNOS5_DRD_PHYSS_TX_VBOOSTLEVEL_OVRD_IN,
> +			  temp);
> +
> +	/*
> +	 * Set proper time to wait for RxDetect measurement, for
> +	 * desired reference clock of PHY, by tuning the CRPORT
> +	 * register LANE0.TX_DEBUG which is internal to PHY.
> +	 * This fixes issue with few USB 3.0 devices, which are
> +	 * not detected (not even generate interrupts on the bus
> +	 * on insertion) without this change.
> +	 * e.g. Samsung SUM-TSB16S 3.0 USB drive.
> +	 */
> +	switch (phy_drd->extrefclk) {
> +	case EXYNOS5_FSEL_50MHZ:
> +		temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_48M_50M_52M;
> +		break;
> +	case EXYNOS5_FSEL_20MHZ:
> +	case EXYNOS5_FSEL_19MHZ2:
> +		temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_19M2_20M;
> +		break;
> +	case EXYNOS5_FSEL_24MHZ:
> +	default:
> +		temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_24M;
> +		break;
> +	}
> +
> +	crport_ctrl_write(phy_drd,
> +			  EXYNOS5_DRD_PHYSS_LANE0_TX_DEBUG,
> +			  temp);
> +}
> +
> +/* Calibrate PIPE3 PHY settings, if any */
> +static int exynos5_usbdrd_pipe3_calibrate(struct phy_usb_instance *inst)
> +{
> +	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
> +
> +	/* Call respective phy_calibrate given by certain platform */
> +	if (phy_drd->drv_data->calibrate)
> +		phy_drd->drv_data->calibrate(phy_drd);
> +
> +	return 0;
> +}
> +
> +static int exynos5_usbdrd_phy_calibrate(struct phy *phy)
> +{
> +	struct phy_usb_instance *inst = phy_get_drvdata(phy);
> +
> +	if (inst->phy_cfg->phy_calibrate)
> +		inst->phy_cfg->phy_calibrate(inst);
> +
> +	return 0;
> +}
> +
>  static struct phy *exynos5_usbdrd_phy_xlate(struct device *dev,
>  					struct of_phandle_args *args)
>  {
> @@ -503,6 +669,7 @@ static struct phy_ops exynos5_usbdrd_phy_ops = {
>  	.exit		= exynos5_usbdrd_phy_exit,
>  	.power_on	= exynos5_usbdrd_phy_power_on,
>  	.power_off	= exynos5_usbdrd_phy_power_off,
> +	.calibrate	= exynos5_usbdrd_phy_calibrate,
>  	.owner		= THIS_MODULE,
>  };
> 
> @@ -518,6 +685,7 @@ static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
>  		.phy_isol	= exynos5_usbdrd_phy_isol,
>  		.phy_init	= exynos5_usbdrd_pipe3_init,
>  		.set_refclk	= exynos5_usbdrd_pipe3_set_refclk,
> +		.phy_calibrate	= exynos5_usbdrd_pipe3_calibrate,
>  	},
>  };
> 
> @@ -525,6 +693,7 @@ static const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = {
>  	.phy_cfg		= phy_cfg_exynos5,
>  	.pmu_offset_usbdrd0_phy	= EXYNOS5_USBDRD_PHY_CONTROL,
>  	.pmu_offset_usbdrd1_phy	= EXYNOS5420_USBDRD1_PHY_CONTROL,
> +	.calibrate		= exynos5420_usbdrd_phy_calibrate,

Hmm, how about adding just flag for this, instead of function callback?
It looks a little bit confusing.

Best regards,
Jingoo Han

>  };
> 
>  static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = {
> --
> 1.7.10.4
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v5 3/4] usb: hcd: Caibrate PHY post hcd reset
  2014-08-22 10:49   ` Andreas Färber
@ 2014-08-28  4:09       ` Vivek Gautam
  0 siblings, 0 replies; 12+ messages in thread
From: Vivek Gautam @ 2014-08-28  4:09 UTC (permalink / raw)
  To: Andreas Färber
  Cc: Linux USB Mailing List, linux-samsung-soc, linux-kernel, Greg KH,
	kishon, Kukjin Kim, Mathias Nyman, Alan Stern, Sergei Shtylyov,
	Heikki Krogerus, Felipe Balbi

Hi,


On Fri, Aug 22, 2014 at 4:19 PM, Andreas Färber <afaerber@suse.de> wrote:
> Hi,
>
> s/Caibrate/Calibrate/

Sure, will rectify the title, thanks for pointing it out.



-- 
Best Regards
Vivek Gautam
Samsung R&D Institute, Bangalore
India

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v5 3/4] usb: hcd: Caibrate PHY post hcd reset
@ 2014-08-28  4:09       ` Vivek Gautam
  0 siblings, 0 replies; 12+ messages in thread
From: Vivek Gautam @ 2014-08-28  4:09 UTC (permalink / raw)
  To: Andreas Färber
  Cc: Linux USB Mailing List, linux-samsung-soc, linux-kernel, Greg KH,
	kishon, Kukjin Kim, Mathias Nyman, Alan Stern, Sergei Shtylyov,
	Heikki Krogerus, Felipe Balbi

Hi,


On Fri, Aug 22, 2014 at 4:19 PM, Andreas Färber <afaerber@suse.de> wrote:
> Hi,
>
> s/Caibrate/Calibrate/

Sure, will rectify the title, thanks for pointing it out.



-- 
Best Regards
Vivek Gautam
Samsung R&D Institute, Bangalore
India

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v5 4/4] phy: exynos5-usbdrd: Calibrate LOS levels for exynos5420/5800
  2014-08-27  1:58     ` Jingoo Han
@ 2014-08-28  4:29       ` Vivek Gautam
  -1 siblings, 0 replies; 12+ messages in thread
From: Vivek Gautam @ 2014-08-28  4:29 UTC (permalink / raw)
  To: Jingoo Han
  Cc: Linux USB Mailing List, linux-samsung-soc, linux-kernel, Greg KH,
	kishon, Kukjin Kim, Mathias Nyman, Alan Stern, Sergei Shtylyov,
	Heikki Krogerus, Felipe Balbi

Hi Jingoo,


On Wed, Aug 27, 2014 at 7:28 AM, Jingoo Han <jg1.han@samsung.com> wrote:
> On Thursday, August 21, 2014 11:55 PM, Vivek Gautam wrote:
>>
>> Adding phy calibrate callback, which facilitates setting certain
>> PHY settings post initialization of the PHY controller.
>> Exynos5420 and Exynos5800 have 28nm USB 3.0 DRD PHY for which
>> the Loss-of-Signal (LOS) Detector Threshold Level as well as
>> Tx-Vboost-Level should be controlled for Super-Speed operations.
>>
>> Additionally set proper time to wait for RxDetect measurement,
>> for desired PHY reference clock, so as to solve issue with enumeration
>> of few USB 3.0 devices, like Samsung SUM-TSB16S 3.0 USB drive
>> on the controller.
>> We are using CR_port for this purpose to send required data
>> to override the LOS values.
>>
>> On testing with USB 3.0 devices on USB 3.0 port present on
>> SMDK5420, and peach-pit boards should see following message:
>> usb 2-1: new SuperSpeed USB device number 2 using xhci-hcd
>>
>> and without this patch, should see below shown message:
>> usb 1-1: new high-speed USB device number 2 using xhci-hcd
>>
>> Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
>> ---
>>  drivers/phy/phy-exynos5-usbdrd.c |  169 ++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 169 insertions(+)
>>
>> diff --git a/drivers/phy/phy-exynos5-usbdrd.c b/drivers/phy/phy-exynos5-usbdrd.c
>> index 47f47fe..fa13784 100644
>> --- a/drivers/phy/phy-exynos5-usbdrd.c
>> +++ b/drivers/phy/phy-exynos5-usbdrd.c
>> @@ -89,8 +89,20 @@
>>  #define PHYCLKRST_COMMONONN                  BIT(0)
>>
>>  #define EXYNOS5_DRD_PHYREG0                  0x14
>> +
>> +#define EXYNOS5_DRD_PHYREG0_SSC_REF_CLK_SEL  BIT(21)
>> +#define EXYNOS5_DRD_PHYREG0_SSC_RANGE                BIT(20)
>> +#define EXYNOS5_DRD_PHYREG0_CR_WRITE         BIT(19)
>> +#define EXYNOS5_DRD_PHYREG0_CR_READ          BIT(18)
>> +#define EXYNOS5_DRD_PHYREG0_CR_DATA_IN(_x)   ((_x) << 2)
>> +#define EXYNOS5_DRD_PHYREG0_CR_CAP_DATA              BIT(1)
>> +#define EXYNOS5_DRD_PHYREG0_CR_CAP_ADDR              BIT(0)
>> +
>>  #define EXYNOS5_DRD_PHYREG1                  0x18
>>
>> +#define EXYNOS5_DRD_PHYREG1_CR_DATA_OUT(_x)  ((_x) << 1)
>> +#define EXYNOS5_DRD_PHYREG1_CR_ACK           BIT(0)
>> +
>>  #define EXYNOS5_DRD_PHYPARAM0                        0x1c
>>
>>  #define PHYPARAM0_REF_USE_PAD                        BIT(31)
>> @@ -118,6 +130,26 @@
>>  #define EXYNOS5_DRD_PHYRESUME                        0x34
>>  #define EXYNOS5_DRD_LINKPORT                 0x44
>>
>> +/* USB 3.0 DRD PHY SS Function Control Reg; accessed by CR_PORT */
>> +#define EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN           (0x15)
>> +
>
> Please remove unnecessary line.

Sure will remove extra lines.

[snip]

>> +static void crport_ctrl_write(struct exynos5_usbdrd_phy *phy_drd,
>> +                                             u32 addr, u32 data)
>> +{
>> +     /* Write Address */
>> +     crport_handshake(phy_drd, EXYNOS5_DRD_PHYREG0_CR_DATA_IN(addr),
>> +                      EXYNOS5_DRD_PHYREG0_CR_CAP_ADDR);
>
> According to the guidance from H/W team, before calling crport_handshake(),
> write access for EXYNOS5_DRD_PHYREG0 register is necessary.
>
> Please, add the write access as follows.
>
> +       /* Write Address */
> +       writel(EXYNOS5_DRD_PHYREG0_CR_DATA_IN(addr),
> +               phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
> +       crport_handshake(phy_drd, EXYNOS5_DRD_PHYREG0_CR_DATA_IN(addr),
> +                        EXYNOS5_DRD_PHYREG0_CR_CAP_ADDR);

Sure will add this, thanks for getting the information from H/W team
and suggesting.

>
> Best regards,
> Jingoo Han
>
>> +
>> +     /* Write Data */
>> +     crport_handshake(phy_drd, EXYNOS5_DRD_PHYREG0_CR_DATA_IN(data),
>> +                      EXYNOS5_DRD_PHYREG0_CR_CAP_DATA);
>> +     crport_handshake(phy_drd, EXYNOS5_DRD_PHYREG0_CR_DATA_IN(data),
>> +                      EXYNOS5_DRD_PHYREG0_CR_WRITE);
>> +}
>> +
>> +/*
>> + * Override PHY paramaeters using CR_PORT register to calibrate settings
>> + * to meet meet SuperSpeed requirements, on Exynos5420 and Exynos5800 systems,
>> + * which have 28nm USB 3.0 DRD PHY.
>> + */
>> +static void exynos5420_usbdrd_phy_calibrate(struct exynos5_usbdrd_phy *phy_drd)
>> +{
>> +     u32 temp;
>> +
>> +     /*
>> +      * Change los_bias to (0x5) for 28nm PHY from a
>> +      * default value (0x0); los_level is set as default
>> +      * (0x9) as also reflected in los_level[30:26] bits
>> +      * of PHYPARAM0 register.
>> +      */
>> +     temp = LOSLEVEL_OVRD_IN_LOS_BIAS_5420 |
>> +             LOSLEVEL_OVRD_IN_EN |
>> +             LOSLEVEL_OVRD_IN_LOS_LEVEL_DEFAULT;
>> +     crport_ctrl_write(phy_drd,
>> +                       EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN,
>> +                       temp);
>> +
>> +     /*
>> +      * Set tx_vboost_lvl to (0x5) for 28nm PHY Tuning,
>> +      * to raise Tx signal level from its default value of (0x4)
>> +      */
>> +     temp = TX_VBOOSTLEVEL_OVRD_IN_VBOOST_5420;
>> +     crport_ctrl_write(phy_drd,
>> +                       EXYNOS5_DRD_PHYSS_TX_VBOOSTLEVEL_OVRD_IN,
>> +                       temp);
>> +
>> +     /*
>> +      * Set proper time to wait for RxDetect measurement, for
>> +      * desired reference clock of PHY, by tuning the CRPORT
>> +      * register LANE0.TX_DEBUG which is internal to PHY.
>> +      * This fixes issue with few USB 3.0 devices, which are
>> +      * not detected (not even generate interrupts on the bus
>> +      * on insertion) without this change.
>> +      * e.g. Samsung SUM-TSB16S 3.0 USB drive.
>> +      */
>> +     switch (phy_drd->extrefclk) {
>> +     case EXYNOS5_FSEL_50MHZ:
>> +             temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_48M_50M_52M;
>> +             break;
>> +     case EXYNOS5_FSEL_20MHZ:
>> +     case EXYNOS5_FSEL_19MHZ2:
>> +             temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_19M2_20M;
>> +             break;
>> +     case EXYNOS5_FSEL_24MHZ:
>> +     default:
>> +             temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_24M;
>> +             break;
>> +     }
>> +
>> +     crport_ctrl_write(phy_drd,
>> +                       EXYNOS5_DRD_PHYSS_LANE0_TX_DEBUG,
>> +                       temp);
>> +}
>> +
>> +/* Calibrate PIPE3 PHY settings, if any */
>> +static int exynos5_usbdrd_pipe3_calibrate(struct phy_usb_instance *inst)
>> +{
>> +     struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
>> +
>> +     /* Call respective phy_calibrate given by certain platform */
>> +     if (phy_drd->drv_data->calibrate)
>> +             phy_drd->drv_data->calibrate(phy_drd);
>> +
>> +     return 0;
>> +}
>> +
>> +static int exynos5_usbdrd_phy_calibrate(struct phy *phy)
>> +{
>> +     struct phy_usb_instance *inst = phy_get_drvdata(phy);
>> +
>> +     if (inst->phy_cfg->phy_calibrate)
>> +             inst->phy_cfg->phy_calibrate(inst);
>> +
>> +     return 0;
>> +}
>> +
>>  static struct phy *exynos5_usbdrd_phy_xlate(struct device *dev,
>>                                       struct of_phandle_args *args)
>>  {
>> @@ -503,6 +669,7 @@ static struct phy_ops exynos5_usbdrd_phy_ops = {
>>       .exit           = exynos5_usbdrd_phy_exit,
>>       .power_on       = exynos5_usbdrd_phy_power_on,
>>       .power_off      = exynos5_usbdrd_phy_power_off,
>> +     .calibrate      = exynos5_usbdrd_phy_calibrate,
>>       .owner          = THIS_MODULE,
>>  };
>>
>> @@ -518,6 +685,7 @@ static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
>>               .phy_isol       = exynos5_usbdrd_phy_isol,
>>               .phy_init       = exynos5_usbdrd_pipe3_init,
>>               .set_refclk     = exynos5_usbdrd_pipe3_set_refclk,
>> +             .phy_calibrate  = exynos5_usbdrd_pipe3_calibrate,
>>       },
>>  };
>>
>> @@ -525,6 +693,7 @@ static const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = {
>>       .phy_cfg                = phy_cfg_exynos5,
>>       .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
>>       .pmu_offset_usbdrd1_phy = EXYNOS5420_USBDRD1_PHY_CONTROL,
>> +     .calibrate              = exynos5420_usbdrd_phy_calibrate,
>
> Hmm, how about adding just flag for this, instead of function callback?
> It looks a little bit confusing.

Yeah, i understand the function pointer name looks a bit confusing
since we are using same name in struct phy_ops too.
But i think keeping a function here for each platform may help in
adding any such support in future SoCs too.

May be we can rename it to phy_exynos_calibrate, if you think
that's fine.
Please let me know your opinion about this.




-- 
Best Regards
Vivek Gautam
Samsung R&D Institute, Bangalore
India

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v5 4/4] phy: exynos5-usbdrd: Calibrate LOS levels for exynos5420/5800
@ 2014-08-28  4:29       ` Vivek Gautam
  0 siblings, 0 replies; 12+ messages in thread
From: Vivek Gautam @ 2014-08-28  4:29 UTC (permalink / raw)
  To: Jingoo Han
  Cc: Linux USB Mailing List, linux-samsung-soc, linux-kernel, Greg KH,
	kishon, Kukjin Kim, Mathias Nyman, Alan Stern, Sergei Shtylyov,
	Heikki Krogerus, Felipe Balbi

Hi Jingoo,


On Wed, Aug 27, 2014 at 7:28 AM, Jingoo Han <jg1.han@samsung.com> wrote:
> On Thursday, August 21, 2014 11:55 PM, Vivek Gautam wrote:
>>
>> Adding phy calibrate callback, which facilitates setting certain
>> PHY settings post initialization of the PHY controller.
>> Exynos5420 and Exynos5800 have 28nm USB 3.0 DRD PHY for which
>> the Loss-of-Signal (LOS) Detector Threshold Level as well as
>> Tx-Vboost-Level should be controlled for Super-Speed operations.
>>
>> Additionally set proper time to wait for RxDetect measurement,
>> for desired PHY reference clock, so as to solve issue with enumeration
>> of few USB 3.0 devices, like Samsung SUM-TSB16S 3.0 USB drive
>> on the controller.
>> We are using CR_port for this purpose to send required data
>> to override the LOS values.
>>
>> On testing with USB 3.0 devices on USB 3.0 port present on
>> SMDK5420, and peach-pit boards should see following message:
>> usb 2-1: new SuperSpeed USB device number 2 using xhci-hcd
>>
>> and without this patch, should see below shown message:
>> usb 1-1: new high-speed USB device number 2 using xhci-hcd
>>
>> Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
>> ---
>>  drivers/phy/phy-exynos5-usbdrd.c |  169 ++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 169 insertions(+)
>>
>> diff --git a/drivers/phy/phy-exynos5-usbdrd.c b/drivers/phy/phy-exynos5-usbdrd.c
>> index 47f47fe..fa13784 100644
>> --- a/drivers/phy/phy-exynos5-usbdrd.c
>> +++ b/drivers/phy/phy-exynos5-usbdrd.c
>> @@ -89,8 +89,20 @@
>>  #define PHYCLKRST_COMMONONN                  BIT(0)
>>
>>  #define EXYNOS5_DRD_PHYREG0                  0x14
>> +
>> +#define EXYNOS5_DRD_PHYREG0_SSC_REF_CLK_SEL  BIT(21)
>> +#define EXYNOS5_DRD_PHYREG0_SSC_RANGE                BIT(20)
>> +#define EXYNOS5_DRD_PHYREG0_CR_WRITE         BIT(19)
>> +#define EXYNOS5_DRD_PHYREG0_CR_READ          BIT(18)
>> +#define EXYNOS5_DRD_PHYREG0_CR_DATA_IN(_x)   ((_x) << 2)
>> +#define EXYNOS5_DRD_PHYREG0_CR_CAP_DATA              BIT(1)
>> +#define EXYNOS5_DRD_PHYREG0_CR_CAP_ADDR              BIT(0)
>> +
>>  #define EXYNOS5_DRD_PHYREG1                  0x18
>>
>> +#define EXYNOS5_DRD_PHYREG1_CR_DATA_OUT(_x)  ((_x) << 1)
>> +#define EXYNOS5_DRD_PHYREG1_CR_ACK           BIT(0)
>> +
>>  #define EXYNOS5_DRD_PHYPARAM0                        0x1c
>>
>>  #define PHYPARAM0_REF_USE_PAD                        BIT(31)
>> @@ -118,6 +130,26 @@
>>  #define EXYNOS5_DRD_PHYRESUME                        0x34
>>  #define EXYNOS5_DRD_LINKPORT                 0x44
>>
>> +/* USB 3.0 DRD PHY SS Function Control Reg; accessed by CR_PORT */
>> +#define EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN           (0x15)
>> +
>
> Please remove unnecessary line.

Sure will remove extra lines.

[snip]

>> +static void crport_ctrl_write(struct exynos5_usbdrd_phy *phy_drd,
>> +                                             u32 addr, u32 data)
>> +{
>> +     /* Write Address */
>> +     crport_handshake(phy_drd, EXYNOS5_DRD_PHYREG0_CR_DATA_IN(addr),
>> +                      EXYNOS5_DRD_PHYREG0_CR_CAP_ADDR);
>
> According to the guidance from H/W team, before calling crport_handshake(),
> write access for EXYNOS5_DRD_PHYREG0 register is necessary.
>
> Please, add the write access as follows.
>
> +       /* Write Address */
> +       writel(EXYNOS5_DRD_PHYREG0_CR_DATA_IN(addr),
> +               phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
> +       crport_handshake(phy_drd, EXYNOS5_DRD_PHYREG0_CR_DATA_IN(addr),
> +                        EXYNOS5_DRD_PHYREG0_CR_CAP_ADDR);

Sure will add this, thanks for getting the information from H/W team
and suggesting.

>
> Best regards,
> Jingoo Han
>
>> +
>> +     /* Write Data */
>> +     crport_handshake(phy_drd, EXYNOS5_DRD_PHYREG0_CR_DATA_IN(data),
>> +                      EXYNOS5_DRD_PHYREG0_CR_CAP_DATA);
>> +     crport_handshake(phy_drd, EXYNOS5_DRD_PHYREG0_CR_DATA_IN(data),
>> +                      EXYNOS5_DRD_PHYREG0_CR_WRITE);
>> +}
>> +
>> +/*
>> + * Override PHY paramaeters using CR_PORT register to calibrate settings
>> + * to meet meet SuperSpeed requirements, on Exynos5420 and Exynos5800 systems,
>> + * which have 28nm USB 3.0 DRD PHY.
>> + */
>> +static void exynos5420_usbdrd_phy_calibrate(struct exynos5_usbdrd_phy *phy_drd)
>> +{
>> +     u32 temp;
>> +
>> +     /*
>> +      * Change los_bias to (0x5) for 28nm PHY from a
>> +      * default value (0x0); los_level is set as default
>> +      * (0x9) as also reflected in los_level[30:26] bits
>> +      * of PHYPARAM0 register.
>> +      */
>> +     temp = LOSLEVEL_OVRD_IN_LOS_BIAS_5420 |
>> +             LOSLEVEL_OVRD_IN_EN |
>> +             LOSLEVEL_OVRD_IN_LOS_LEVEL_DEFAULT;
>> +     crport_ctrl_write(phy_drd,
>> +                       EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN,
>> +                       temp);
>> +
>> +     /*
>> +      * Set tx_vboost_lvl to (0x5) for 28nm PHY Tuning,
>> +      * to raise Tx signal level from its default value of (0x4)
>> +      */
>> +     temp = TX_VBOOSTLEVEL_OVRD_IN_VBOOST_5420;
>> +     crport_ctrl_write(phy_drd,
>> +                       EXYNOS5_DRD_PHYSS_TX_VBOOSTLEVEL_OVRD_IN,
>> +                       temp);
>> +
>> +     /*
>> +      * Set proper time to wait for RxDetect measurement, for
>> +      * desired reference clock of PHY, by tuning the CRPORT
>> +      * register LANE0.TX_DEBUG which is internal to PHY.
>> +      * This fixes issue with few USB 3.0 devices, which are
>> +      * not detected (not even generate interrupts on the bus
>> +      * on insertion) without this change.
>> +      * e.g. Samsung SUM-TSB16S 3.0 USB drive.
>> +      */
>> +     switch (phy_drd->extrefclk) {
>> +     case EXYNOS5_FSEL_50MHZ:
>> +             temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_48M_50M_52M;
>> +             break;
>> +     case EXYNOS5_FSEL_20MHZ:
>> +     case EXYNOS5_FSEL_19MHZ2:
>> +             temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_19M2_20M;
>> +             break;
>> +     case EXYNOS5_FSEL_24MHZ:
>> +     default:
>> +             temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_24M;
>> +             break;
>> +     }
>> +
>> +     crport_ctrl_write(phy_drd,
>> +                       EXYNOS5_DRD_PHYSS_LANE0_TX_DEBUG,
>> +                       temp);
>> +}
>> +
>> +/* Calibrate PIPE3 PHY settings, if any */
>> +static int exynos5_usbdrd_pipe3_calibrate(struct phy_usb_instance *inst)
>> +{
>> +     struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
>> +
>> +     /* Call respective phy_calibrate given by certain platform */
>> +     if (phy_drd->drv_data->calibrate)
>> +             phy_drd->drv_data->calibrate(phy_drd);
>> +
>> +     return 0;
>> +}
>> +
>> +static int exynos5_usbdrd_phy_calibrate(struct phy *phy)
>> +{
>> +     struct phy_usb_instance *inst = phy_get_drvdata(phy);
>> +
>> +     if (inst->phy_cfg->phy_calibrate)
>> +             inst->phy_cfg->phy_calibrate(inst);
>> +
>> +     return 0;
>> +}
>> +
>>  static struct phy *exynos5_usbdrd_phy_xlate(struct device *dev,
>>                                       struct of_phandle_args *args)
>>  {
>> @@ -503,6 +669,7 @@ static struct phy_ops exynos5_usbdrd_phy_ops = {
>>       .exit           = exynos5_usbdrd_phy_exit,
>>       .power_on       = exynos5_usbdrd_phy_power_on,
>>       .power_off      = exynos5_usbdrd_phy_power_off,
>> +     .calibrate      = exynos5_usbdrd_phy_calibrate,
>>       .owner          = THIS_MODULE,
>>  };
>>
>> @@ -518,6 +685,7 @@ static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
>>               .phy_isol       = exynos5_usbdrd_phy_isol,
>>               .phy_init       = exynos5_usbdrd_pipe3_init,
>>               .set_refclk     = exynos5_usbdrd_pipe3_set_refclk,
>> +             .phy_calibrate  = exynos5_usbdrd_pipe3_calibrate,
>>       },
>>  };
>>
>> @@ -525,6 +693,7 @@ static const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = {
>>       .phy_cfg                = phy_cfg_exynos5,
>>       .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
>>       .pmu_offset_usbdrd1_phy = EXYNOS5420_USBDRD1_PHY_CONTROL,
>> +     .calibrate              = exynos5420_usbdrd_phy_calibrate,
>
> Hmm, how about adding just flag for this, instead of function callback?
> It looks a little bit confusing.

Yeah, i understand the function pointer name looks a bit confusing
since we are using same name in struct phy_ops too.
But i think keeping a function here for each platform may help in
adding any such support in future SoCs too.

May be we can rename it to phy_exynos_calibrate, if you think
that's fine.
Please let me know your opinion about this.




-- 
Best Regards
Vivek Gautam
Samsung R&D Institute, Bangalore
India

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2014-08-28  4:29 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-21 14:55 [PATCH v5 0/4] Fine tune USB 3.0 PHY on exynos5420 Vivek Gautam
2014-08-21 14:55 ` [PATCH v5 1/4] phy: Add provision for calibrating phy Vivek Gautam
2014-08-21 14:55 ` [PATCH v5 2/4] usb: host: xhci-plat: Get PHYs for xhci's hcds Vivek Gautam
2014-08-21 14:55 ` [PATCH v5 3/4] usb: hcd: Caibrate PHY post hcd reset Vivek Gautam
2014-08-22 10:49   ` Andreas Färber
2014-08-28  4:09     ` Vivek Gautam
2014-08-28  4:09       ` Vivek Gautam
2014-08-21 14:55 ` [PATCH v5 4/4] phy: exynos5-usbdrd: Calibrate LOS levels for exynos5420/5800 Vivek Gautam
2014-08-27  1:58   ` Jingoo Han
2014-08-27  1:58     ` Jingoo Han
2014-08-28  4:29     ` Vivek Gautam
2014-08-28  4:29       ` Vivek Gautam

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.