2019-06-27 07:18:14

by Marek Szyprowski

[permalink] [raw]
Subject: [PATCH 0/3] Fix USB3.0 DRD PHY calibration issues (DWC3/XHCI) on Exynos542x SoCs

Dear All,

Commit d8c80bb3b55b ("phy: exynos5-usbdrd: Calibrate LOS levels for
exynos5420/5800") added support for Exynos5 USB3.0 DRD PHY calibration,
what enabled proper Super-Speed enumeration of USB3.0 devices connected
to various Exynos5 SoCs. After some time it turned out that the mentioned
patch worked a bit by pure luck and covered only one use case (fresh
boot with all drivers compiled into the kernel).

If drivers were compiled as modules, due to timing issue, it worked only
if XHCI-plat driver was loaded before the DWC3 driver:
https://patchwork.kernel.org/patch/10773947/

Also during the system suspend/resume cycle the calibration was not
performed at the proper time and resulted in switching USB 3.0 devices to
USB 2.0 high-speed compatibility mode.

This patch addresses all those issues. Exynos5 USB3.0 DRD PHY calibration
is moved to the Exynos5 specific variant of the XHCI-plat driver, which
takes care of proper PHY calibration after XHCI core reset. This fixes
all known use cases (XHCI driver compiled as module and loaded on demand
as well as during system suspend/resume cycle).

Here are the logs taken on Exynos5422-based Odroid HC1 board (with USB3.0
RTL8153 LAN and USB3.0 JMicron SATA-USB bridge):

Vanilla Linux next-20190620:
----->8-----------------------------------------------------------------
root@target:~# lsusb -t
/: Bus 06.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 5000M
|__ Port 1: Dev 2, If 0, Class=Vendor Specific Class, Driver=r8152, 5000M
/: Bus 05.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 480M
/: Bus 04.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 5000M
|__ Port 1: Dev 2, If 0, Class=Mass Storage, Driver=uas, 5000M
/: Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 480M
/: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=exynos-ohci/3p, 12M
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=exynos-ehci/3p, 480M
root@target:~# time rtcwake -s 10 -m mem
rtcwake: wakeup from "mem" using /dev/rtc0 at Tue Jan 1 01:03:40 2019
[ 31.372801] PM: suspend entry (deep)
[ 31.376555] Filesystems sync: 0.001 seconds
[ 31.396437] Freezing user space processes ... (elapsed 0.006 seconds) done.
[ 31.408300] OOM killer disabled.
[ 31.411329] Freezing remaining freezable tasks ... (elapsed 0.002 seconds) done.
[ 31.419336] printk: Suspending console(s) (use no_console_suspend to debug)
[ 31.508432] sd 0:0:0:0: [sda] Synchronizing SCSI cache
[ 31.586243] wake enabled for irq 145
[ 31.748908] samsung-pinctrl 13400000.pinctrl: Setting external wakeup interrupt mask: 0xffffffef
[ 31.758671] Disabling non-boot CPUs ...
[ 31.772117] IRQ 51: no longer affine to CPU1
[ 31.782147] IRQ 52: no longer affine to CPU2
[ 31.789290] IRQ 53: no longer affine to CPU3
[ 31.792439] IRQ 54: no longer affine to CPU4
[ 31.794942] IRQ 55: no longer affine to CPU5
[ 31.797365] IRQ 56: no longer affine to CPU6
[ 31.801387] IRQ 57: no longer affine to CPU7
[ 31.811149] Enabling non-boot CPUs ...
[ 31.815607] CPU1 is up
[ 31.818790] CPU2 is up
[ 31.821709] CPU3 is up
[ 31.826095] CPU4 is up
[ 31.828672] CPU5 is up
[ 31.831215] CPU6 is up
[ 31.834158] CPU7 is up
[ 31.859900] s3c2410-wdt 101d0000.watchdog: watchdog disabled
[ 31.860158] usb usb1: root hub lost power or was reset
[ 31.931175] usb usb2: root hub lost power or was reset
[ 31.940717] wake disabled for irq 145
[ 31.949146] usb usb3: root hub lost power or was reset
[ 31.949235] usb usb4: root hub lost power or was reset
[ 31.949329] s3c-rtc 101e0000.rtc: rtc disabled, re-enabling
[ 31.950751] usb usb5: root hub lost power or was reset
[ 31.950773] usb usb6: root hub lost power or was reset
[ 36.201351] OOM killer enabled.
[ 36.204381] Restarting tasks ...
[ 36.206110] usb 4-1: USB disconnect, device number 2
[ 36.206529] usb 6-1: USB disconnect, device number 2
[ 36.210588] done.
[ 36.220679] PM: suspend exit

real 0m15.613s
user 0m0.000s
sys 0m0.329s
[ 36.237525] sd 0:0:0:0: [sda] Synchronizing SCSI cache
[ 36.254403] mmc_host mmc0: Bus speed (slot 0) = 50000000Hz (slot req 400000Hz, actual 396825HZ div = 63)
root@target:~# [ 36.341609] mmc_host mmc0: Bus speed (slot 0) = 200000000Hz (slot req 200000000Hz, actual 200000000HZ div = 0)
[ 36.597244] usb 5-1: new high-speed USB device number 3 using xhci-hcd
[ 36.837573] sd 0:0:0:0: [sda] Synchronize Cache(10) failed: Result: hostbyte=0x07 driverbyte=0x00
[ 37.099089] usb 5-1: New USB device found, idVendor=0bda, idProduct=8153, bcdDevice=30.00
[ 37.105793] usb 5-1: New USB device strings: Mfr=1, Product=2, SerialNumber=6
[ 37.112962] usb 5-1: Product: USB 10/100/1000 LAN
[ 37.117629] usb 5-1: Manufacturer: Realtek
[ 37.121645] usb 5-1: SerialNumber: 000001000000
[ 37.373152] usb 5-1: reset high-speed USB device number 3 using xhci-hcd
[ 37.407459] usb usb3-port1: Cannot enable. Maybe the USB cable is bad?
[ 37.664128] r8152 5-1:1.0 eth0: v1.09.9
[ 38.437326] usb 3-1: new high-speed USB device number 3 using xhci-hcd
[ 38.628713] usb 3-1: New USB device found, idVendor=152d, idProduct=0578, bcdDevice= 1.05
[ 38.635470] usb 3-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 38.642803] usb 3-1: Product: USB to SATA bridge
[ 38.647321] usb 3-1: Manufacturer: JMicron
[ 38.651232] usb 3-1: SerialNumber: DB00000000013B
[ 38.678606] scsi host0: uas
[ 38.687425] scsi 0:0:0:0: Direct-Access JMicron 0105 PQ: 0 ANSI: 6
[ 38.704216] sd 0:0:0:0: Attached scsi generic sg0 type 0
[ 38.710333] sd 0:0:0:0: [sda] 1953525168 512-byte logical blocks: (1.00 TB/932 GiB)
[ 38.716641] sd 0:0:0:0: [sda] 4096-byte physical blocks
[ 38.723383] sd 0:0:0:0: [sda] Write Protect is off
[ 38.730019] sd 0:0:0:0: [sda] Disabling FUA
[ 38.732737] sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[ 38.743524] sd 0:0:0:0: [sda] Optimal transfer size 33553920 bytes not a multiple of physical block size (4096 bytes)
[ 38.855590] sda: sda1 sda2 sda3 sda4 < sda5 sda6 >
[ 38.887585] sd 0:0:0:0: [sda] Attached SCSI disk
[ 40.968358] usb usb6-port1: Cannot enable. Maybe the USB cable is bad?
[ 45.288065] usb usb6-port1: Cannot enable. Maybe the USB cable is bad?

root@target:~# lsusb -t
/: Bus 06.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 5000M
/: Bus 05.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 480M
|__ Port 1: Dev 3, If 0, Class=Vendor Specific Class, Driver=r8152, 480M
/: Bus 04.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 5000M
/: Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 480M
|__ Port 1: Dev 3, If 0, Class=Mass Storage, Driver=uas, 480M
/: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=exynos-ohci/3p, 12M
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=exynos-ehci/3p, 480M
root@target:~#
----->8-----------------------------------------------------------------


Linux next-20190620 with this patchset applied:
----->8-----------------------------------------------------------------
root@target:~# lsusb -t
/: Bus 06.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 5000M
|__ Port 1: Dev 2, If 0, Class=Vendor Specific Class, Driver=r8152, 5000M
/: Bus 05.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 480M
/: Bus 04.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 5000M
|__ Port 1: Dev 2, If 0, Class=Mass Storage, Driver=uas, 5000M
/: Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 480M
/: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=exynos-ohci/3p, 12M
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=exynos-ehci/3p, 480M
root@target:~# time rtcwake -s 10 -m mem
rtcwake: wakeup from "mem" using /dev/rtc0 at Tue Jan 1 01:08:06 2019
[ 33.057518] PM: suspend entry (deep)
[ 33.068116] Filesystems sync: 0.007 seconds
[ 33.100867] Freezing user space processes ... (elapsed 0.004 seconds) done.
[ 33.110697] OOM killer disabled.
[ 33.113758] Freezing remaining freezable tasks ... (elapsed 0.001 seconds) done.
[ 33.121699] printk: Suspending console(s) (use no_console_suspend to debug)
[ 33.206799] sd 0:0:0:0: [sda] Synchronizing SCSI cache
[ 33.284135] wake enabled for irq 145
[ 33.447955] samsung-pinctrl 13400000.pinctrl: Setting external wakeup interrupt mask: 0xffffffef
[ 33.459351] Disabling non-boot CPUs ...
[ 33.469730] IRQ 51: no longer affine to CPU1
[ 33.478596] IRQ 52: no longer affine to CPU2
[ 33.484306] IRQ 53: no longer affine to CPU3
[ 33.487255] IRQ 54: no longer affine to CPU4
[ 33.490071] IRQ 55: no longer affine to CPU5
[ 33.492706] IRQ 56: no longer affine to CPU6
[ 33.496822] IRQ 57: no longer affine to CPU7
[ 33.503482] Enabling non-boot CPUs ...
[ 33.508159] CPU1 is up
[ 33.511114] CPU2 is up
[ 33.514131] CPU3 is up
[ 33.518772] CPU4 is up
[ 33.521219] CPU5 is up
[ 33.523782] CPU6 is up
[ 33.526860] CPU7 is up
[ 33.551393] s3c2410-wdt 101d0000.watchdog: watchdog disabled
[ 33.551651] usb usb1: root hub lost power or was reset
[ 33.619193] usb usb2: root hub lost power or was reset
[ 33.628517] wake disabled for irq 145
[ 33.636675] usb usb3: root hub lost power or was reset
[ 33.636768] usb usb4: root hub lost power or was reset
[ 33.636883] s3c-rtc 101e0000.rtc: rtc disabled, re-enabling
[ 33.636915] usb usb5: root hub lost power or was reset
[ 33.636931] usb usb6: root hub lost power or was reset
[ 37.556700] usb 4-1: reset SuperSpeed Gen 1 USB device number 2 using xhci-hcd
[ 37.890524] OOM killer enabled.
[ 37.893600] Restarting tasks ...
[ 37.895049] usb 6-1: USB disconnect, device number 2
[ 37.897862] done.
[ 37.904761] PM: suspend exit

real 0m14.651s
user 0m0.000s
sys 0m0.360s
[ 37.931922] mmc_host mmc0: Bus speed (slot 0) = 50000000Hz (slot req 400000Hz, actual 396825HZ div = 63)
root@target:~# [ 38.025326] mmc_host mmc0: Bus speed (slot 0) = 200000000Hz (slot req 200000000Hz, actual 200000000HZ div = 0)
[ 38.895675] usb 6-1: new SuperSpeed Gen 1 USB device number 3 using xhci-hcd
[ 38.929327] usb 6-1: New USB device found, idVendor=0bda, idProduct=8153, bcdDevice=30.00
[ 38.936156] usb 6-1: New USB device strings: Mfr=1, Product=2, SerialNumber=6
[ 38.943157] usb 6-1: Product: USB 10/100/1000 LAN
[ 38.947944] usb 6-1: Manufacturer: Realtek
[ 38.951891] usb 6-1: SerialNumber: 000001000000
[ 39.215806] usb 6-1: reset SuperSpeed Gen 1 USB device number 3 using xhci-hcd
[ 39.351893] r8152 6-1:1.0 eth0: v1.09.9

root@target:~# lsusb -t
/: Bus 06.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 5000M
|__ Port 1: Dev 3, If 0, Class=Vendor Specific Class, Driver=r8152, 5000M
/: Bus 05.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 480M
/: Bus 04.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 5000M
|__ Port 1: Dev 2, If 0, Class=Mass Storage, Driver=uas, 5000M
/: Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 480M
/: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=exynos-ohci/3p, 12M
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=exynos-ehci/3p, 480M
root@target:~#
----->8-----------------------------------------------------------------


Best regards
Marek Szyprowski
Samsung R&D Institute Poland


Patch summary:

Marek Szyprowski (3):
usb: host: xhci-plat: Add support for Exynos5/DWC3 specific variant
usb: dwc3: exynos: Use Exynos specific XHCI-plat driver variant
usb: dwc3: Remove generic PHY calibrate() calls

drivers/usb/dwc3/Kconfig | 1 +
drivers/usb/dwc3/core.c | 3 +-
drivers/usb/dwc3/core.h | 1 +
drivers/usb/dwc3/dwc3-exynos.c | 64 +++++++++++++++++++++++-----------
drivers/usb/dwc3/host.c | 2 +-
drivers/usb/host/Kconfig | 8 +++++
drivers/usb/host/Makefile | 3 ++
drivers/usb/host/xhci-exynos.c | 51 +++++++++++++++++++++++++++
drivers/usb/host/xhci-exynos.h | 26 ++++++++++++++
drivers/usb/host/xhci-plat.c | 38 +++++++++++++++++++-
drivers/usb/host/xhci-plat.h | 2 ++
11 files changed, 174 insertions(+), 25 deletions(-)
create mode 100644 drivers/usb/host/xhci-exynos.c
create mode 100644 drivers/usb/host/xhci-exynos.h

--
2.17.1


2019-06-27 07:18:15

by Marek Szyprowski

[permalink] [raw]
Subject: [PATCH 1/3] usb: host: xhci-plat: Add support for Exynos5/DWC3 specific variant

USB3.0 DRD PHY found in Exynos5 SoCs requires calibration to be done
after every HCD reset. This was initially handled by DWC3 core by commit
d8c80bb3b55b ("phy: exynos5-usbdrd: Calibrate LOS levels for
exynos5420/5800"), but it turned out that the mentioned patch worked only
by the pure luck and fixed only one use case.

PHY calibration was done in DWC3 driver, just before initializing XHCI
core. This approach was prone to a race. It worked for the fresh boot
case iff XHCI-plat driver was compiled into the kernel or it's module has
been loaded before DWC3 probe. In other cases (XHCI-plat module loaded on
demand after DWC3 probe or during suspend/resume cycle) - the
calibration was not performed at proper time and had no effect.

This patch creates Exynos5/DWC3 specific variant of XHCI-plat driver,
which takes care of proper PHY calibration after XHCI core reset, what
fixes all known use cases (XHCI driver compiled as module and loaded on
demand as well as during system suspend/resume cycle).

Signed-off-by: Marek Szyprowski <[email protected]>
---
drivers/usb/host/Kconfig | 8 ++++++
drivers/usb/host/Makefile | 3 ++
drivers/usb/host/xhci-exynos.c | 51 ++++++++++++++++++++++++++++++++++
drivers/usb/host/xhci-exynos.h | 26 +++++++++++++++++
drivers/usb/host/xhci-plat.c | 38 ++++++++++++++++++++++++-
drivers/usb/host/xhci-plat.h | 2 ++
6 files changed, 127 insertions(+), 1 deletion(-)
create mode 100644 drivers/usb/host/xhci-exynos.c
create mode 100644 drivers/usb/host/xhci-exynos.h

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 40b5de597112..5a17a9b1fbff 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -53,6 +53,14 @@ config USB_XHCI_PLATFORM

If unsure, say N.

+config USB_XHCI_EXYNOS
+ tristate "xHCI support for Samsung Exynos SoCs"
+ depends on USB_XHCI_PLATFORM
+ depends on ARCH_EXYNOS || COMPILE_TEST
+ ---help---
+ Say 'Y' to enable the support for the xHCI host controller
+ found in Samsung Exynos ARM SoCs.
+
config USB_XHCI_HISTB
tristate "xHCI support for HiSilicon STB SoCs"
depends on USB_XHCI_PLATFORM && (ARCH_HISI || COMPILE_TEST)
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 84514f71ae44..34afd6680751 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -30,6 +30,9 @@ endif
ifneq ($(CONFIG_USB_XHCI_RCAR), )
xhci-plat-hcd-y += xhci-rcar.o
endif
+ifneq ($(CONFIG_USB_XHCI_EXYNOS), )
+ xhci-plat-hcd-y += xhci-exynos.o
+endif

ifneq ($(CONFIG_DEBUG_FS),)
xhci-hcd-y += xhci-debugfs.o
diff --git a/drivers/usb/host/xhci-exynos.c b/drivers/usb/host/xhci-exynos.c
new file mode 100644
index 000000000000..446d33998382
--- /dev/null
+++ b/drivers/usb/host/xhci-exynos.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * xHCI host controller driver for Samsung Exynos5 SoCs
+ *
+ * Copyright (C) 2019 Samsung Electronics Co., Ltd.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+
+#include "xhci.h"
+#include "xhci-plat.h"
+#include "xhci-exynos.h"
+
+int xhci_exynos_init_quirk(struct usb_hcd *hcd)
+{
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ struct device *dev = hcd->self.controller;
+ struct xhci_plat_priv *xhci_priv = hcd_to_xhci_priv(hcd);
+ struct phy *usb2_generic_phy;
+ int ret;
+
+ usb2_generic_phy = devm_phy_get(dev->parent, "usb2-phy");
+ if (IS_ERR(usb2_generic_phy)) {
+ ret = PTR_ERR(usb2_generic_phy);
+ if (ret == -EPROBE_DEFER) {
+ return ret;
+ } else {
+ dev_err(dev, "no usb2 phy configured\n");
+ return ret;
+ }
+ }
+
+ phy_calibrate(usb2_generic_phy);
+ xhci_priv->priv = usb2_generic_phy;
+
+ xhci->quirks |= XHCI_RESET_ON_RESUME;
+
+ return 0;
+}
+
+int xhci_exynos_post_resume_quirk(struct usb_hcd *hcd)
+{
+ struct xhci_plat_priv *xhci_priv = hcd_to_xhci_priv(hcd);
+ struct phy *usb2_generic_phy = xhci_priv->priv;
+
+ phy_calibrate(usb2_generic_phy);
+
+ return 0;
+}
diff --git a/drivers/usb/host/xhci-exynos.h b/drivers/usb/host/xhci-exynos.h
new file mode 100644
index 000000000000..58ea3e9aea8d
--- /dev/null
+++ b/drivers/usb/host/xhci-exynos.h
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * drivers/usb/host/xhci-exynos.h
+ *
+ * Copyright (C) 2019 Samsung Electronics Co., Ltd.
+ */
+
+#ifndef _XHCI_EXYNOS_H
+#define _XHCI_EXYNOS_H
+
+
+#if IS_ENABLED(CONFIG_USB_XHCI_EXYNOS)
+int xhci_exynos_init_quirk(struct usb_hcd *hcd);
+int xhci_exynos_post_resume_quirk(struct usb_hcd *hcd);
+#else
+static inline int xhci_exynos_init_quirk(struct usb_hcd *hcd)
+{
+ return 0;
+}
+
+static inline int xhci_exynos_post_resume_quirk(struct usb_hcd *hcd)
+{
+ return 0;
+}
+#endif
+#endif /* _XHCI_EXYNOS_H */
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 998241f5fce3..6bc03cdb2f21 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -24,6 +24,7 @@
#include "xhci-plat.h"
#include "xhci-mvebu.h"
#include "xhci-rcar.h"
+#include "xhci-exynos.h"

static struct hc_driver __read_mostly xhci_plat_hc_driver;

@@ -64,6 +65,16 @@ static int xhci_priv_resume_quirk(struct usb_hcd *hcd)
return priv->resume_quirk(hcd);
}

+static int xhci_priv_post_resume_quirk(struct usb_hcd *hcd)
+{
+ struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd);
+
+ if (!priv->post_resume_quirk)
+ return 0;
+
+ return priv->post_resume_quirk(hcd);
+}
+
static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci)
{
/*
@@ -102,6 +113,11 @@ static const struct xhci_plat_priv xhci_plat_marvell_armada3700 = {
.init_quirk = xhci_mvebu_a3700_init_quirk,
};

+static const struct xhci_plat_priv xhci_plat_samsung_exynos5 = {
+ .init_quirk = xhci_exynos_init_quirk,
+ .post_resume_quirk = xhci_exynos_post_resume_quirk,
+};
+
static const struct xhci_plat_priv xhci_plat_renesas_rcar_gen2 = {
.firmware_name = XHCI_RCAR_FIRMWARE_NAME_V1,
.init_quirk = xhci_rcar_init_quirk,
@@ -260,6 +276,13 @@ static int xhci_plat_probe(struct platform_device *pdev)
goto disable_reg_clk;

priv_match = of_device_get_match_data(&pdev->dev);
+ if (!priv_match) {
+ const struct platform_device_id *id =
+ platform_get_device_id(pdev);
+ if (id)
+ priv_match = (const struct xhci_plat_priv *)
+ id->driver_data;
+ }
if (priv_match) {
struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd);

@@ -413,7 +436,11 @@ static int __maybe_unused xhci_plat_resume(struct device *dev)
if (ret)
return ret;

- return xhci_resume(xhci, 0);
+ ret = xhci_resume(xhci, 0);
+ if (ret)
+ return ret;
+
+ return xhci_priv_post_resume_quirk(hcd);
}

static int __maybe_unused xhci_plat_runtime_suspend(struct device *dev)
@@ -447,9 +474,18 @@ static const struct acpi_device_id usb_xhci_acpi_match[] = {
};
MODULE_DEVICE_TABLE(acpi, usb_xhci_acpi_match);

+static struct platform_device_id xhci_plat_driver_ids[] = {
+ {
+ .name = "exynos5-dwc3-xhci",
+ .driver_data = (long) &xhci_plat_samsung_exynos5,
+ }, { },
+};
+MODULE_DEVICE_TABLE(platform, xhci_plat_driver_ids);
+
static struct platform_driver usb_xhci_driver = {
.probe = xhci_plat_probe,
.remove = xhci_plat_remove,
+ .id_table = xhci_plat_driver_ids,
.driver = {
.name = "xhci-hcd",
.pm = &xhci_plat_pm_ops,
diff --git a/drivers/usb/host/xhci-plat.h b/drivers/usb/host/xhci-plat.h
index ae29f22ff5bd..f8a8e84b4ebe 100644
--- a/drivers/usb/host/xhci-plat.h
+++ b/drivers/usb/host/xhci-plat.h
@@ -12,9 +12,11 @@

struct xhci_plat_priv {
const char *firmware_name;
+ void *priv;
void (*plat_start)(struct usb_hcd *);
int (*init_quirk)(struct usb_hcd *);
int (*resume_quirk)(struct usb_hcd *);
+ int (*post_resume_quirk)(struct usb_hcd *);
};

#define hcd_to_xhci_priv(h) ((struct xhci_plat_priv *)hcd_to_xhci(h)->priv)
--
2.17.1

2019-06-27 07:18:24

by Marek Szyprowski

[permalink] [raw]
Subject: [PATCH 2/3] usb: dwc3: exynos: Use Exynos specific XHCI-plat driver variant

Exynos5 SoCs needs to calibrate USB3.0 DRD PHY after every XHCI HCD
reset. This patch adds support for instantiating Exynos5-specific variant
of XHCI-plat driver, which handles the required USB3.0 DRD PHY
calibration.

Signed-off-by: Marek Szyprowski <[email protected]>
---
drivers/usb/dwc3/Kconfig | 1 +
drivers/usb/dwc3/core.c | 1 +
drivers/usb/dwc3/core.h | 1 +
drivers/usb/dwc3/dwc3-exynos.c | 64 +++++++++++++++++++++++-----------
drivers/usb/dwc3/host.c | 2 +-
5 files changed, 47 insertions(+), 22 deletions(-)

diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index 89abc6078703..badf86dfb027 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -67,6 +67,7 @@ config USB_DWC3_OMAP
config USB_DWC3_EXYNOS
tristate "Samsung Exynos Platform"
depends on (ARCH_EXYNOS || COMPILE_TEST) && OF
+ select USB_XHCI_EXYNOS if USB_XHCI_PLATFORM
default USB_DWC3
help
Recent Exynos5 SoCs ship with one DesignWare Core USB3 IP inside,
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index c9bb93a2c81e..baa029ceede9 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -1303,6 +1303,7 @@ static void dwc3_get_properties(struct dwc3 *dwc)
&dwc->hsphy_interface);
device_property_read_u32(dev, "snps,quirk-frame-length-adjustment",
&dwc->fladj);
+ device_property_read_string(dev, "snps,xhci_variant", &dwc->hcd_name);

dwc->dis_metastability_quirk = device_property_read_bool(dev,
"snps,dis_metastability_quirk");
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 3dd783b889cb..1b8f5f5814a4 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -1176,6 +1176,7 @@ struct dwc3 {
u8 tx_max_burst_prd;

const char *hsphy_interface;
+ const char *hcd_name;

unsigned connected:1;
unsigned delayed_status:1;
diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c
index c1e9ea621f41..4e847073e85e 100644
--- a/drivers/usb/dwc3/dwc3-exynos.c
+++ b/drivers/usb/dwc3/dwc3-exynos.c
@@ -13,6 +13,7 @@
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/dma-mapping.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/regulator/consumer.h>
@@ -35,22 +36,20 @@ struct dwc3_exynos {

struct regulator *vdd33;
struct regulator *vdd10;
+ struct platform_device *dwc3;
};

-static int dwc3_exynos_remove_child(struct device *dev, void *unused)
-{
- struct platform_device *pdev = to_platform_device(dev);
-
- platform_device_unregister(pdev);
-
- return 0;
-}
+static const struct property_entry dwc3_exynos_properties[] = {
+ PROPERTY_ENTRY_STRING("snps,xhci_variant", "exynos5-dwc3-xhci"),
+ {}
+};

static int dwc3_exynos_probe(struct platform_device *pdev)
{
struct dwc3_exynos *exynos;
struct device *dev = &pdev->dev;
- struct device_node *node = dev->of_node;
+ struct device_node *node = dev->of_node, *child;
+ struct platform_device *dwc3;
const struct dwc3_exynos_driverdata *driver_data;
int i, ret;

@@ -109,21 +108,43 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
goto vdd10_err;
}

- if (node) {
- ret = of_platform_populate(node, NULL, NULL, dev);
- if (ret) {
- dev_err(dev, "failed to add dwc3 core\n");
- goto populate_err;
- }
- } else {
- dev_err(dev, "no device node, failed to add dwc3 core\n");
- ret = -ENODEV;
- goto populate_err;
+ child = of_get_next_child(node, NULL);
+ if (!child) {
+ dev_err(dev, "Failed to find DWC3 core device node\n");
+ goto dwc3_child_err;
+ }
+
+ dwc3 = of_device_alloc(child, NULL, dev);
+ if (!dwc3) {
+ dev_err(dev, "Failed to allocate DWC3 core device\n");
+ goto dwc3_alloc_err;
+ }
+
+ dwc3->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+ dwc3->dev.dma_mask = &dwc3->dev.coherent_dma_mask;
+ dwc3->dev.bus = &platform_bus_type;
+
+ ret = platform_device_add_properties(dwc3, dwc3_exynos_properties);
+ if (ret < 0) {
+ dev_err(dev, "Failed to add properties to DWC3 device\n");
+ goto dwc3_props_err;
+ }
+
+ ret = of_device_add(dwc3);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to register DWC3 core device\n");
+ goto dwc3_props_err;
}
+ exynos->dwc3 = dwc3;
+ of_node_put(child);

return 0;

-populate_err:
+dwc3_props_err:
+ platform_device_put(dwc3);
+dwc3_alloc_err:
+ of_node_put(child);
+dwc3_child_err:
regulator_disable(exynos->vdd10);
vdd10_err:
regulator_disable(exynos->vdd33);
@@ -142,7 +163,8 @@ static int dwc3_exynos_remove(struct platform_device *pdev)
struct dwc3_exynos *exynos = platform_get_drvdata(pdev);
int i;

- device_for_each_child(&pdev->dev, NULL, dwc3_exynos_remove_child);
+ of_device_unregister(exynos->dwc3);
+ platform_device_put(exynos->dwc3);

for (i = exynos->num_clks - 1; i >= 0; i--)
clk_disable_unprepare(exynos->clks[i]);
diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
index f55947294f7c..b526d0c78c3b 100644
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -71,7 +71,7 @@ int dwc3_host_init(struct dwc3 *dwc)
dwc->xhci_resources[1].flags = res->flags;
dwc->xhci_resources[1].name = res->name;

- xhci = platform_device_alloc("xhci-hcd", PLATFORM_DEVID_AUTO);
+ xhci = platform_device_alloc(dwc->hcd_name, PLATFORM_DEVID_AUTO);
if (!xhci) {
dev_err(dwc->dev, "couldn't allocate xHCI device\n");
return -ENOMEM;
--
2.17.1

2019-06-27 07:18:53

by Marek Szyprowski

[permalink] [raw]
Subject: [PATCH 3/3] usb: dwc3: Remove generic PHY calibrate() calls

Calls to USB2 generic PHY calibrate() method were added by commit
d8c80bb3b55b ("phy: exynos5-usbdrd: Calibrate LOS levels for
exynos5420/5800"), but it turned out that the mentioned patch worked only
by the pure luck and fixed only one use case. To fix the issues with PHY
calibration it has been moved to XHCI HCD driver, what allows to perform
calibration in the proper time window. This patch removes those calls
from DWC3 driver, as they are no longer needed there.

Signed-off-by: Marek Szyprowski <[email protected]>
---
drivers/usb/dwc3/core.c | 2 --
1 file changed, 2 deletions(-)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index baa029ceede9..f62e8442c614 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -168,7 +168,6 @@ static void __dwc3_set_mode(struct work_struct *work)
otg_set_vbus(dwc->usb2_phy->otg, true);
phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST);
phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST);
- phy_calibrate(dwc->usb2_generic_phy);
}
break;
case DWC3_GCTL_PRTCAP_DEVICE:
@@ -1166,7 +1165,6 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)
dev_err(dev, "failed to initialize host\n");
return ret;
}
- phy_calibrate(dwc->usb2_generic_phy);
break;
case USB_DR_MODE_OTG:
INIT_WORK(&dwc->drd_work, __dwc3_set_mode);
--
2.17.1

2019-06-28 15:33:45

by Anand Moon

[permalink] [raw]
Subject: Re: [PATCH 0/3] Fix USB3.0 DRD PHY calibration issues (DWC3/XHCI) on Exynos542x SoCs

Hi Marek,

On Thu, 27 Jun 2019 at 12:47, Marek Szyprowski <[email protected]> wrote:
>
> Dear All,
>
> Commit d8c80bb3b55b ("phy: exynos5-usbdrd: Calibrate LOS levels for
> exynos5420/5800") added support for Exynos5 USB3.0 DRD PHY calibration,
> what enabled proper Super-Speed enumeration of USB3.0 devices connected
> to various Exynos5 SoCs. After some time it turned out that the mentioned
> patch worked a bit by pure luck and covered only one use case (fresh
> boot with all drivers compiled into the kernel).
>
> If drivers were compiled as modules, due to timing issue, it worked only
> if XHCI-plat driver was loaded before the DWC3 driver:
> https://patchwork.kernel.org/patch/10773947/
>
> Also during the system suspend/resume cycle the calibration was not
> performed at the proper time and resulted in switching USB 3.0 devices to
> USB 2.0 high-speed compatibility mode.
>
> This patch addresses all those issues. Exynos5 USB3.0 DRD PHY calibration
> is moved to the Exynos5 specific variant of the XHCI-plat driver, which
> takes care of proper PHY calibration after XHCI core reset. This fixes
> all known use cases (XHCI driver compiled as module and loaded on demand
> as well as during system suspend/resume cycle).
>
> Here are the logs taken on Exynos5422-based Odroid HC1 board (with USB3.0
> RTL8153 LAN and USB3.0 JMicron SATA-USB bridge):
>

Thanks for these patch. I have tested on linux-next-20190626

*But hotpluging of usb device is not working on usb ports.*


These patches fix the suspend/resume for XU4.
But their is two issue.
1> On warm boot fails to reset the usb hub
------------------------------------------------------------------
[ 7.019896] usb 4-1.1: new SuperSpeed Gen 1 USB device number 3
using xhci-hcd
[ 7.063032] usb 4-1.1: New USB device found, idVendor=152d,
idProduct=0578, bcdDevice=63.01
[ 7.070484] usb 4-1.1: New USB device strings: Mfr=1, Product=2,
SerialNumber=3
[ 7.077438] usb 4-1.1: Product: JMS567
[ 7.081749] usb 4-1.1: Manufacturer: JMicron
[ 7.086028] usb 4-1.1: SerialNumber: DB12345678A3
[ 7.151572] scsi host0: uas
[ 7.162765] scsi 0:0:0:0: Direct-Access KINGSTON SA400S37120G
6301 PQ: 0 ANSI: 6
[ 7.176231] sd 0:0:0:0: [sda] 234441648 512-byte logical blocks:
(120 GB/112 GiB)
[ 7.177550] sd 0:0:0:0: Attached scsi generic sg0 type 0
[ 7.183547] sd 0:0:0:0: [sda] 4096-byte physical blocks
[ 7.201150] sd 0:0:0:0: [sda] Write Protect is off
[ 7.204977] sd 0:0:0:0: [sda] Disabling FUA
[ 7.209476] sd 0:0:0:0: [sda] Write cache: enabled, read cache:
enabled, doesn't support DPO or FUA
[ 7.219411] sd 0:0:0:0: [sda] Optimal transfer size 33553920 bytes
not a multiple of physical block size (4096 bytes)
[ 7.713603] sda: sda1
[ 7.736338] sd 0:0:0:0: [sda] Attached SCSI disk
[ 11.372630] xhci-hcd exynos5-dwc3-xhci.5.auto: Timeout while
waiting for setup device command
[ 16.650624] xhci-hcd exynos5-dwc3-xhci.5.auto: Timeout while
waiting for setup device command
[ 16.870255] usb 6-1: device not accepting address 2, error -62
[ 22.171093] xhci-hcd exynos5-dwc3-xhci.5.auto: Timeout while
waiting for setup device command
[ 27.451021] xhci-hcd exynos5-dwc3-xhci.5.auto: Timeout while
waiting for setup device command
[ 27.669956] usb 6-1: device not accepting address 3, error -62
[ 27.711656] usb usb6-port1: attempt power cycle

some how 12500000.phy do not de-register when we perform reboot.

[ 120.260813] shutdown[1]: All loop devices detached.
[ 120.308592] sd 0:0:0:0: [sda] Synchronizing SCSI cache
[ 120.425890] usb 4-1.1: reset SuperSpeed Gen 1 USB device number 3
using xhci-hcd
[ 120.500085] wake enabled for irq 155
[ 120.592335] reboot: Restartin

Attach are the reboot logs.
[0] https://pastebin.com/a3d712q4

Second issue is the unbind on usb dwc3 fails.

[root@archl-xu4m ~]# cd /sys/bus/platform/drivers/exynos5_usb3drd_phy/
[root@archl-xu4m exynos5_usb3drd_phy]# ls -la
total 0
drwxr-xr-x 2 root root 0 Jun 28 14:08 .
drwxr-xr-x 131 root root 0 Jun 28 14:08 ..
lrwxrwxrwx 1 root root 0 Jun 28 14:11 12100000.phy ->
../../../../devices/platform/soc/12100000.phy
lrwxrwxrwx 1 root root 0 Jun 28 14:11 12500000.phy ->
../../../../devices/platform/soc/12500000.phy
--w------- 1 root root 4096 Jun 28 14:11 bind
--w------- 1 root root 4096 Jun 28 14:08 uevent
--w------- 1 root root 4096 Jun 28 14:11 unbind
[root@archl-xu4m exynos5_usb3drd_phy]#
[root@archl-xu4m exynos5_usb3drd_phy]#
[root@archl-xu4m exynos5_usb3drd_phy]# echo 12500000.phy > unbind
[ 194.138492] ------------[ cut here ]------------
[ 194.142104] WARNING: CPU: 6 PID: 292 at
drivers/regulator/core.c:2036 _regulator_put.part.4+0x110/0x118
[ 194.156913] Modules linked in: s5p_mfc s5p_jpeg exynos_gsc
v4l2_mem2mem v4l2_common videobuf2_dma_contig videobuf2_memops
videobuf2_v4l2 videobuf2_common videodev mc s5p_cec
[ 194.171542] CPU: 6 PID: 292 Comm: bash Not tainted
5.2.0-rc6-next-20190626-xu4ml #21
[ 194.178963] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
[ 194.184983] [<c0112794>] (unwind_backtrace) from [<c010dfec>]
(show_stack+0x10/0x14)
[ 194.192732] [<c010dfec>] (show_stack) from [<c0ab30c0>]
(dump_stack+0x98/0xc4)
[ 194.199887] [<c0ab30c0>] (dump_stack) from [<c0127b78>]
(__warn.part.3+0xbc/0xec)
[ 194.207332] [<c0127b78>] (__warn.part.3) from [<c0127d10>]
(warn_slowpath_null+0x44/0x4c)
[ 194.215491] [<c0127d10>] (warn_slowpath_null) from [<c04f8f3c>]
(_regulator_put.part.4+0x110/0x118)
[ 194.224518] [<c04f8f3c>] (_regulator_put.part.4) from [<c04f8f70>]
(regulator_put+0x2c/0x3c)
[ 194.232916] [<c04f8f70>] (regulator_put) from [<c05b8eb8>]
(release_nodes+0x1c0/0x204)
[ 194.240791] [<c05b8eb8>] (release_nodes) from [<c05b4f20>]
(device_release_driver_internal+0xec/0x1ac)
[ 194.250086] [<c05b4f20>] (device_release_driver_internal) from
[<c05b2d38>] (unbind_store+0x60/0xd4)
[ 194.259189] [<c05b2d38>] (unbind_store) from [<c03332dc>]
(kernfs_fop_write+0x100/0x1e0)
[ 194.267232] [<c03332dc>] (kernfs_fop_write) from [<c02a2f60>]
(__vfs_write+0x30/0x1c4)
[ 194.275110] [<c02a2f60>] (__vfs_write) from [<c02a5a74>]
(vfs_write+0xa4/0x184)
[ 194.282376] [<c02a5a74>] (vfs_write) from [<c02a5ccc>] (ksys_write+0x5c/0xd4)
[ 194.289472] [<c02a5ccc>] (ksys_write) from [<c0101000>]
(ret_fast_syscall+0x0/0x28)
[ 194.297103] Exception stack(0xe50fbfa8 to 0xe50fbff0)
[ 194.302074] bfa0: 0000000d 0054a958 00000001
0054a958 0000000d 00000000
[ 194.310284] bfc0: 0000000d 0054a958 b6e7ebc8 00000004 0054a958
0000000d 00000000 00000000
[ 194.318424] bfe0: 00000070 be9e1868 b6da3c80 b6dff784
[ 194.323614] irq event stamp: 20491
[ 194.326920] hardirqs last enabled at (20515): [<c0199aac>]
console_unlock+0x440/0x64c
[ 194.334720] hardirqs last disabled at (20522): [<c0199714>]
console_unlock+0xa8/0x64c
[ 194.342690] softirqs last enabled at (20540): [<c0102544>]
__do_softirq+0x35c/0x654
[ 194.350403] softirqs last disabled at (20553): [<c012fd80>]
irq_exit+0x158/0x16c
[ 194.357782] ---[ end trace 5ea20768939447c5 ]---
[ 194.363628] ------------[ cut here ]------------
[ 194.367095] WARNING: CPU: 6 PID: 292 at
drivers/regulator/core.c:2036 _regulator_put.part.4+0x110/0x118
[ 194.376360] Modules linked in: s5p_mfc s5p_jpeg exynos_gsc
v4l2_mem2mem v4l2_common videobuf2_dma_contig videobuf2_memops
videobuf2_v4l2 videobuf2_common videodev mc s5p_cec
[ 194.392067] CPU: 6 PID: 292 Comm: bash Tainted: G W
5.2.0-rc6-next-20190626-xu4ml #21
[ 194.400882] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
[ 194.406902] [<c0112794>] (unwind_backtrace) from [<c010dfec>]
(show_stack+0x10/0x14)
[ 194.414647] [<c010dfec>] (show_stack) from [<c0ab30c0>]
(dump_stack+0x98/0xc4)
[ 194.421825] [<c0ab30c0>] (dump_stack) from [<c0127b78>]
(__warn.part.3+0xbc/0xec)
[ 194.429284] [<c0127b78>] (__warn.part.3) from [<c0127d10>]
(warn_slowpath_null+0x44/0x4c)
[ 194.437441] [<c0127d10>] (warn_slowpath_null) from [<c04f8f3c>]
(_regulator_put.part.4+0x110/0x118)
[ 194.446469] [<c04f8f3c>] (_regulator_put.part.4) from [<c04f8f70>]
(regulator_put+0x2c/0x3c)
[ 194.454868] [<c04f8f70>] (regulator_put) from [<c05b8eb8>]
(release_nodes+0x1c0/0x204)
[ 194.462743] [<c05b8eb8>] (release_nodes) from [<c05b4f20>]
(device_release_driver_internal+0xec/0x1ac)
[ 194.472038] [<c05b4f20>] (device_release_driver_internal) from
[<c05b2d38>] (unbind_store+0x60/0xd4)
[ 194.481135] [<c05b2d38>] (unbind_store) from [<c03332dc>]
(kernfs_fop_write+0x100/0x1e0)
[ 194.489175] [<c03332dc>] (kernfs_fop_write) from [<c02a2f60>]
(__vfs_write+0x30/0x1c4)
[ 194.497056] [<c02a2f60>] (__vfs_write) from [<c02a5a74>]
(vfs_write+0xa4/0x184)
[ 194.504323] [<c02a5a74>] (vfs_write) from [<c02a5ccc>] (ksys_write+0x5c/0xd4)
[ 194.511417] [<c02a5ccc>] (ksys_write) from [<c0101000>]
(ret_fast_syscall+0x0/0x28)
[ 194.519050] Exception stack(0xe50fbfa8 to 0xe50fbff0)
[ 194.524020] bfa0: 0000000d 0054a958 00000001
0054a958 0000000d 00000000
[ 194.532231] bfc0: 0000000d 0054a958 b6e7ebc8 00000004 0054a958
0000000d 00000000 00000000
[ 194.540372] bfe0: 00000070 be9e1868 b6da3c80 b6dff784
[ 194.545640] irq event stamp: 20765
[ 194.548824] hardirqs last enabled at (20785): [<c0199aac>]
console_unlock+0x440/0x64c
[ 194.556794] hardirqs last disabled at (20802): [<c0199714>]
console_unlock+0xa8/0x64c
[ 194.564468] softirqs last enabled at (20800): [<c0102544>]
__do_softirq+0x35c/0x654
[ 194.572329] softirqs last disabled at (20819): [<c012fd80>]
irq_exit+0x158/0x16c
[ 194.579679] ---[ end trace 5ea20768939447c6 ]---
[root@archl-xu4m exynos5_usb3drd_phy]#

I saw the peripherals get on/off during suspend resume but on no
regulator disable/enable calls.

Attach are the logs
[2] https://pastebin.com/uQT2EYgX

Best Regards
-Anand

2019-07-15 12:20:37

by Marek Szyprowski

[permalink] [raw]
Subject: Re: [PATCH 0/3] Fix USB3.0 DRD PHY calibration issues (DWC3/XHCI) on Exynos542x SoCs

Hi Anand,

On 2019-06-28 17:32, Anand Moon wrote:
> Hi Marek,
>
> On Thu, 27 Jun 2019 at 12:47, Marek Szyprowski <[email protected]> wrote:
>> Dear All,
>>
>> Commit d8c80bb3b55b ("phy: exynos5-usbdrd: Calibrate LOS levels for
>> exynos5420/5800") added support for Exynos5 USB3.0 DRD PHY calibration,
>> what enabled proper Super-Speed enumeration of USB3.0 devices connected
>> to various Exynos5 SoCs. After some time it turned out that the mentioned
>> patch worked a bit by pure luck and covered only one use case (fresh
>> boot with all drivers compiled into the kernel).
>>
>> If drivers were compiled as modules, due to timing issue, it worked only
>> if XHCI-plat driver was loaded before the DWC3 driver:
>> https://patchwork.kernel.org/patch/10773947/
>>
>> Also during the system suspend/resume cycle the calibration was not
>> performed at the proper time and resulted in switching USB 3.0 devices to
>> USB 2.0 high-speed compatibility mode.
>>
>> This patch addresses all those issues. Exynos5 USB3.0 DRD PHY calibration
>> is moved to the Exynos5 specific variant of the XHCI-plat driver, which
>> takes care of proper PHY calibration after XHCI core reset. This fixes
>> all known use cases (XHCI driver compiled as module and loaded on demand
>> as well as during system suspend/resume cycle).
>>
>> Here are the logs taken on Exynos5422-based Odroid HC1 board (with USB3.0
>> RTL8153 LAN and USB3.0 JMicron SATA-USB bridge):
>>
> Thanks for these patch. I have tested on linux-next-20190626
>
> *But hotpluging of usb device is not working on usb ports.*

Well, this is a bit poor report. I've checked various USB 3.0 devices
with my XU4 board and didn't observe any issue with hotplug or
enumeration. Could you describe a bit more how to trigger the issue?

> These patches fix the suspend/resume for XU4.
> But their is two issue.
> 1> On warm boot fails to reset the usb hub
> ------------------------------------------------------------------
> [ 7.019896] usb 4-1.1: new SuperSpeed Gen 1 USB device number 3
> using xhci-hcd
> [ 7.063032] usb 4-1.1: New USB device found, idVendor=152d,
> idProduct=0578, bcdDevice=63.01
> [ 7.070484] usb 4-1.1: New USB device strings: Mfr=1, Product=2,
> SerialNumber=3
> [ 7.077438] usb 4-1.1: Product: JMS567
> [ 7.081749] usb 4-1.1: Manufacturer: JMicron
> [ 7.086028] usb 4-1.1: SerialNumber: DB12345678A3
> [ 7.151572] scsi host0: uas
> [ 7.162765] scsi 0:0:0:0: Direct-Access KINGSTON SA400S37120G
> 6301 PQ: 0 ANSI: 6
> [ 7.176231] sd 0:0:0:0: [sda] 234441648 512-byte logical blocks:
> (120 GB/112 GiB)
> [ 7.177550] sd 0:0:0:0: Attached scsi generic sg0 type 0
> [ 7.183547] sd 0:0:0:0: [sda] 4096-byte physical blocks
> [ 7.201150] sd 0:0:0:0: [sda] Write Protect is off
> [ 7.204977] sd 0:0:0:0: [sda] Disabling FUA
> [ 7.209476] sd 0:0:0:0: [sda] Write cache: enabled, read cache:
> enabled, doesn't support DPO or FUA
> [ 7.219411] sd 0:0:0:0: [sda] Optimal transfer size 33553920 bytes
> not a multiple of physical block size (4096 bytes)
> [ 7.713603] sda: sda1
> [ 7.736338] sd 0:0:0:0: [sda] Attached SCSI disk
> [ 11.372630] xhci-hcd exynos5-dwc3-xhci.5.auto: Timeout while
> waiting for setup device command
> [ 16.650624] xhci-hcd exynos5-dwc3-xhci.5.auto: Timeout while
> waiting for setup device command
> [ 16.870255] usb 6-1: device not accepting address 2, error -62
> [ 22.171093] xhci-hcd exynos5-dwc3-xhci.5.auto: Timeout while
> waiting for setup device command
> [ 27.451021] xhci-hcd exynos5-dwc3-xhci.5.auto: Timeout while
> waiting for setup device command
> [ 27.669956] usb 6-1: device not accepting address 3, error -62
> [ 27.711656] usb usb6-port1: attempt power cycle
>
> some how 12500000.phy do not de-register when we perform reboot.

Sorry, but this is not related to PHY at all. If I get your log right,
you have external USB3->SATA bridge which fails to enumerate in your
case. Does it work right with other boards or vendor kernels? You
connect it to the XU4 onboard USB3.0 hub, which cannot be programmed or
controlled in any way, so I doubt we can do anything to fix your issue.


> [ 120.260813] shutdown[1]: All loop devices detached.
> [ 120.308592] sd 0:0:0:0: [sda] Synchronizing SCSI cache
> [ 120.425890] usb 4-1.1: reset SuperSpeed Gen 1 USB device number 3
> using xhci-hcd
> [ 120.500085] wake enabled for irq 155
> [ 120.592335] reboot: Restartin
>
> Attach are the reboot logs.
> [0] https://pastebin.com/a3d712q4
>
> Second issue is the unbind on usb dwc3 fails.
>
> [root@archl-xu4m ~]# cd /sys/bus/platform/drivers/exynos5_usb3drd_phy/
> [root@archl-xu4m exynos5_usb3drd_phy]# ls -la
> total 0
> drwxr-xr-x 2 root root 0 Jun 28 14:08 .
> drwxr-xr-x 131 root root 0 Jun 28 14:08 ..
> lrwxrwxrwx 1 root root 0 Jun 28 14:11 12100000.phy ->
> ../../../../devices/platform/soc/12100000.phy
> lrwxrwxrwx 1 root root 0 Jun 28 14:11 12500000.phy ->
> ../../../../devices/platform/soc/12500000.phy
> --w------- 1 root root 4096 Jun 28 14:11 bind
> --w------- 1 root root 4096 Jun 28 14:08 uevent
> --w------- 1 root root 4096 Jun 28 14:11 unbind
> [root@archl-xu4m exynos5_usb3drd_phy]#
> [root@archl-xu4m exynos5_usb3drd_phy]#
> [root@archl-xu4m exynos5_usb3drd_phy]# echo 12500000.phy > unbind

This is not dwc3 unbind, but USB3.0 DRD PHY unbind. This is somehow
expected as unbinding on fly a device, which provides resources to other
driver (in this case USB phys) causes various issues due to the Linux
kernel frameworks design. Please don't try such things, it won't work.
Exynos DRD PHY driver should be marked with suppress_bind flag to hide
bind/unbind attributes.


> [ 194.138492] ------------[ cut here ]------------
> [ 194.142104] WARNING: CPU: 6 PID: 292 at
> drivers/regulator/core.c:2036 _regulator_put.part.4+0x110/0x118
> [ 194.156913] Modules linked in: s5p_mfc s5p_jpeg exynos_gsc
> v4l2_mem2mem v4l2_common videobuf2_dma_contig videobuf2_memops
> videobuf2_v4l2 videobuf2_common videodev mc s5p_cec
> [ 194.171542] CPU: 6 PID: 292 Comm: bash Not tainted
> 5.2.0-rc6-next-20190626-xu4ml #21
> [ 194.178963] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
> [ 194.184983] [<c0112794>] (unwind_backtrace) from [<c010dfec>]
> (show_stack+0x10/0x14)
> [ 194.192732] [<c010dfec>] (show_stack) from [<c0ab30c0>]
> (dump_stack+0x98/0xc4)
> [ 194.199887] [<c0ab30c0>] (dump_stack) from [<c0127b78>]
> (__warn.part.3+0xbc/0xec)
> [ 194.207332] [<c0127b78>] (__warn.part.3) from [<c0127d10>]
> (warn_slowpath_null+0x44/0x4c)
> [ 194.215491] [<c0127d10>] (warn_slowpath_null) from [<c04f8f3c>]
> (_regulator_put.part.4+0x110/0x118)
> [ 194.224518] [<c04f8f3c>] (_regulator_put.part.4) from [<c04f8f70>]
> (regulator_put+0x2c/0x3c)
> [ 194.232916] [<c04f8f70>] (regulator_put) from [<c05b8eb8>]
> (release_nodes+0x1c0/0x204)
> [ 194.240791] [<c05b8eb8>] (release_nodes) from [<c05b4f20>]
> (device_release_driver_internal+0xec/0x1ac)
> [ 194.250086] [<c05b4f20>] (device_release_driver_internal) from
> [<c05b2d38>] (unbind_store+0x60/0xd4)
> [ 194.259189] [<c05b2d38>] (unbind_store) from [<c03332dc>]
> (kernfs_fop_write+0x100/0x1e0)
> [ 194.267232] [<c03332dc>] (kernfs_fop_write) from [<c02a2f60>]
> (__vfs_write+0x30/0x1c4)
> [ 194.275110] [<c02a2f60>] (__vfs_write) from [<c02a5a74>]
> (vfs_write+0xa4/0x184)
> [ 194.282376] [<c02a5a74>] (vfs_write) from [<c02a5ccc>] (ksys_write+0x5c/0xd4)
> [ 194.289472] [<c02a5ccc>] (ksys_write) from [<c0101000>]
> (ret_fast_syscall+0x0/0x28)
> [ 194.297103] Exception stack(0xe50fbfa8 to 0xe50fbff0)
> [ 194.302074] bfa0: 0000000d 0054a958 00000001
> 0054a958 0000000d 00000000
> [ 194.310284] bfc0: 0000000d 0054a958 b6e7ebc8 00000004 0054a958
> 0000000d 00000000 00000000
> [ 194.318424] bfe0: 00000070 be9e1868 b6da3c80 b6dff784
> [ 194.323614] irq event stamp: 20491
> [ 194.326920] hardirqs last enabled at (20515): [<c0199aac>]
> console_unlock+0x440/0x64c
> [ 194.334720] hardirqs last disabled at (20522): [<c0199714>]
> console_unlock+0xa8/0x64c
> [ 194.342690] softirqs last enabled at (20540): [<c0102544>]
> __do_softirq+0x35c/0x654
> [ 194.350403] softirqs last disabled at (20553): [<c012fd80>]
> irq_exit+0x158/0x16c
> [ 194.357782] ---[ end trace 5ea20768939447c5 ]---
> [ 194.363628] ------------[ cut here ]------------
> [ 194.367095] WARNING: CPU: 6 PID: 292 at
> drivers/regulator/core.c:2036 _regulator_put.part.4+0x110/0x118
> [ 194.376360] Modules linked in: s5p_mfc s5p_jpeg exynos_gsc
> v4l2_mem2mem v4l2_common videobuf2_dma_contig videobuf2_memops
> videobuf2_v4l2 videobuf2_common videodev mc s5p_cec
> [ 194.392067] CPU: 6 PID: 292 Comm: bash Tainted: G W
> 5.2.0-rc6-next-20190626-xu4ml #21
> [ 194.400882] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
> [ 194.406902] [<c0112794>] (unwind_backtrace) from [<c010dfec>]
> (show_stack+0x10/0x14)
> [ 194.414647] [<c010dfec>] (show_stack) from [<c0ab30c0>]
> (dump_stack+0x98/0xc4)
> [ 194.421825] [<c0ab30c0>] (dump_stack) from [<c0127b78>]
> (__warn.part.3+0xbc/0xec)
> [ 194.429284] [<c0127b78>] (__warn.part.3) from [<c0127d10>]
> (warn_slowpath_null+0x44/0x4c)
> [ 194.437441] [<c0127d10>] (warn_slowpath_null) from [<c04f8f3c>]
> (_regulator_put.part.4+0x110/0x118)
> [ 194.446469] [<c04f8f3c>] (_regulator_put.part.4) from [<c04f8f70>]
> (regulator_put+0x2c/0x3c)
> [ 194.454868] [<c04f8f70>] (regulator_put) from [<c05b8eb8>]
> (release_nodes+0x1c0/0x204)
> [ 194.462743] [<c05b8eb8>] (release_nodes) from [<c05b4f20>]
> (device_release_driver_internal+0xec/0x1ac)
> [ 194.472038] [<c05b4f20>] (device_release_driver_internal) from
> [<c05b2d38>] (unbind_store+0x60/0xd4)
> [ 194.481135] [<c05b2d38>] (unbind_store) from [<c03332dc>]
> (kernfs_fop_write+0x100/0x1e0)
> [ 194.489175] [<c03332dc>] (kernfs_fop_write) from [<c02a2f60>]
> (__vfs_write+0x30/0x1c4)
> [ 194.497056] [<c02a2f60>] (__vfs_write) from [<c02a5a74>]
> (vfs_write+0xa4/0x184)
> [ 194.504323] [<c02a5a74>] (vfs_write) from [<c02a5ccc>] (ksys_write+0x5c/0xd4)
> [ 194.511417] [<c02a5ccc>] (ksys_write) from [<c0101000>]
> (ret_fast_syscall+0x0/0x28)
> [ 194.519050] Exception stack(0xe50fbfa8 to 0xe50fbff0)
> [ 194.524020] bfa0: 0000000d 0054a958 00000001
> 0054a958 0000000d 00000000
> [ 194.532231] bfc0: 0000000d 0054a958 b6e7ebc8 00000004 0054a958
> 0000000d 00000000 00000000
> [ 194.540372] bfe0: 00000070 be9e1868 b6da3c80 b6dff784
> [ 194.545640] irq event stamp: 20765
> [ 194.548824] hardirqs last enabled at (20785): [<c0199aac>]
> console_unlock+0x440/0x64c
> [ 194.556794] hardirqs last disabled at (20802): [<c0199714>]
> console_unlock+0xa8/0x64c
> [ 194.564468] softirqs last enabled at (20800): [<c0102544>]
> __do_softirq+0x35c/0x654
> [ 194.572329] softirqs last disabled at (20819): [<c012fd80>]
> irq_exit+0x158/0x16c
> [ 194.579679] ---[ end trace 5ea20768939447c6 ]---
> [root@archl-xu4m exynos5_usb3drd_phy]#
>
> I saw the peripherals get on/off during suspend resume but on no
> regulator disable/enable calls.

There is no such need and the regulators are shared during runtime, so
they will be on anyway.

> Attach are the logs
> [2] https://pastebin.com/uQT2EYgX

Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland

2019-07-15 18:31:30

by Anand Moon

[permalink] [raw]
Subject: Re: [PATCH 0/3] Fix USB3.0 DRD PHY calibration issues (DWC3/XHCI) on Exynos542x SoCs

Hi Marek,

On Mon, 15 Jul 2019 at 17:49, Marek Szyprowski <[email protected]> wrote:
>
> Hi Anand,
>
> On 2019-06-28 17:32, Anand Moon wrote:
> > Hi Marek,
> >
> > On Thu, 27 Jun 2019 at 12:47, Marek Szyprowski <[email protected]> wrote:
> >> Dear All,
> >>
> >> Commit d8c80bb3b55b ("phy: exynos5-usbdrd: Calibrate LOS levels for
> >> exynos5420/5800") added support for Exynos5 USB3.0 DRD PHY calibration,
> >> what enabled proper Super-Speed enumeration of USB3.0 devices connected
> >> to various Exynos5 SoCs. After some time it turned out that the mentioned
> >> patch worked a bit by pure luck and covered only one use case (fresh
> >> boot with all drivers compiled into the kernel).
> >>
> >> If drivers were compiled as modules, due to timing issue, it worked only
> >> if XHCI-plat driver was loaded before the DWC3 driver:
> >> https://patchwork.kernel.org/patch/10773947/
> >>
> >> Also during the system suspend/resume cycle the calibration was not
> >> performed at the proper time and resulted in switching USB 3.0 devices to
> >> USB 2.0 high-speed compatibility mode.
> >>
> >> This patch addresses all those issues. Exynos5 USB3.0 DRD PHY calibration
> >> is moved to the Exynos5 specific variant of the XHCI-plat driver, which
> >> takes care of proper PHY calibration after XHCI core reset. This fixes
> >> all known use cases (XHCI driver compiled as module and loaded on demand
> >> as well as during system suspend/resume cycle).
> >>
> >> Here are the logs taken on Exynos5422-based Odroid HC1 board (with USB3.0
> >> RTL8153 LAN and USB3.0 JMicron SATA-USB bridge):
> >>
> > Thanks for these patch. I have tested on linux-next-20190626
> >
> > *But hotpluging of usb device is not working on usb ports.*
>
> Well, this is a bit poor report. I've checked various USB 3.0 devices
> with my XU4 board and didn't observe any issue with hotplug or
> enumeration. Could you describe a bit more how to trigger the issue?
>

Sorry for the noise one of my usb 3.0 port on XU4 is not working somehow.
I will re-test these patches again on current next and share my result.

> > These patches fix the suspend/resume for XU4.
> > But their is two issue.
> > 1> On warm boot fails to reset the usb hub
> > ------------------------------------------------------------------
> > [ 7.019896] usb 4-1.1: new SuperSpeed Gen 1 USB device number 3
> > using xhci-hcd
> > [ 7.063032] usb 4-1.1: New USB device found, idVendor=152d,
> > idProduct=0578, bcdDevice=63.01
> > [ 7.070484] usb 4-1.1: New USB device strings: Mfr=1, Product=2,
> > SerialNumber=3
> > [ 7.077438] usb 4-1.1: Product: JMS567
> > [ 7.081749] usb 4-1.1: Manufacturer: JMicron
> > [ 7.086028] usb 4-1.1: SerialNumber: DB12345678A3
> > [ 7.151572] scsi host0: uas
> > [ 7.162765] scsi 0:0:0:0: Direct-Access KINGSTON SA400S37120G
> > 6301 PQ: 0 ANSI: 6
> > [ 7.176231] sd 0:0:0:0: [sda] 234441648 512-byte logical blocks:
> > (120 GB/112 GiB)
> > [ 7.177550] sd 0:0:0:0: Attached scsi generic sg0 type 0
> > [ 7.183547] sd 0:0:0:0: [sda] 4096-byte physical blocks
> > [ 7.201150] sd 0:0:0:0: [sda] Write Protect is off
> > [ 7.204977] sd 0:0:0:0: [sda] Disabling FUA
> > [ 7.209476] sd 0:0:0:0: [sda] Write cache: enabled, read cache:
> > enabled, doesn't support DPO or FUA
> > [ 7.219411] sd 0:0:0:0: [sda] Optimal transfer size 33553920 bytes
> > not a multiple of physical block size (4096 bytes)
> > [ 7.713603] sda: sda1
> > [ 7.736338] sd 0:0:0:0: [sda] Attached SCSI disk
> > [ 11.372630] xhci-hcd exynos5-dwc3-xhci.5.auto: Timeout while
> > waiting for setup device command
> > [ 16.650624] xhci-hcd exynos5-dwc3-xhci.5.auto: Timeout while
> > waiting for setup device command
> > [ 16.870255] usb 6-1: device not accepting address 2, error -62
> > [ 22.171093] xhci-hcd exynos5-dwc3-xhci.5.auto: Timeout while
> > waiting for setup device command
> > [ 27.451021] xhci-hcd exynos5-dwc3-xhci.5.auto: Timeout while
> > waiting for setup device command
> > [ 27.669956] usb 6-1: device not accepting address 3, error -62
> > [ 27.711656] usb usb6-port1: attempt power cycle
> >
> > some how 12500000.phy do not de-register when we perform reboot.
>
> Sorry, but this is not related to PHY at all. If I get your log right,
> you have external USB3->SATA bridge which fails to enumerate in your
> case. Does it work right with other boards or vendor kernels? You
> connect it to the XU4 onboard USB3.0 hub, which cannot be programmed or
> controlled in any way, so I doubt we can do anything to fix your issue.
>

Sorry this issue is related to realtek ethernet driver r-8153 failed
to register again
after reboot. It's a know issue for long time as far as I know,
I will double check this again.

>
> > [ 120.260813] shutdown[1]: All loop devices detached.
> > [ 120.308592] sd 0:0:0:0: [sda] Synchronizing SCSI cache
> > [ 120.425890] usb 4-1.1: reset SuperSpeed Gen 1 USB device number 3
> > using xhci-hcd
> > [ 120.500085] wake enabled for irq 155
> > [ 120.592335] reboot: Restartin
> >
> > Attach are the reboot logs.
> > [0] https://pastebin.com/a3d712q4
> >
> > Second issue is the unbind on usb dwc3 fails.
> >
> > [root@archl-xu4m ~]# cd /sys/bus/platform/drivers/exynos5_usb3drd_phy/
> > [root@archl-xu4m exynos5_usb3drd_phy]# ls -la
> > total 0
> > drwxr-xr-x 2 root root 0 Jun 28 14:08 .
> > drwxr-xr-x 131 root root 0 Jun 28 14:08 ..
> > lrwxrwxrwx 1 root root 0 Jun 28 14:11 12100000.phy ->
> > ../../../../devices/platform/soc/12100000.phy
> > lrwxrwxrwx 1 root root 0 Jun 28 14:11 12500000.phy ->
> > ../../../../devices/platform/soc/12500000.phy
> > --w------- 1 root root 4096 Jun 28 14:11 bind
> > --w------- 1 root root 4096 Jun 28 14:08 uevent
> > --w------- 1 root root 4096 Jun 28 14:11 unbind
> > [root@archl-xu4m exynos5_usb3drd_phy]#
> > [root@archl-xu4m exynos5_usb3drd_phy]#
> > [root@archl-xu4m exynos5_usb3drd_phy]# echo 12500000.phy > unbind
>
> This is not dwc3 unbind, but USB3.0 DRD PHY unbind. This is somehow
> expected as unbinding on fly a device, which provides resources to other
> driver (in this case USB phys) causes various issues due to the Linux
> kernel frameworks design. Please don't try such things, it won't work.
> Exynos DRD PHY driver should be marked with suppress_bind flag to hide
> bind/unbind attributes.
>

Ok thanks for your inputs and suggestion.

> Best regards
> --
> Marek Szyprowski, PhD
> Samsung R&D Institute Poland
>

Best Regards


-Anand

2019-07-16 17:32:46

by Anand Moon

[permalink] [raw]
Subject: Re: [PATCH 1/3] usb: host: xhci-plat: Add support for Exynos5/DWC3 specific variant

Hi Marek,

On Thu, 27 Jun 2019 at 12:47, Marek Szyprowski <[email protected]> wrote:
>
> USB3.0 DRD PHY found in Exynos5 SoCs requires calibration to be done
> after every HCD reset. This was initially handled by DWC3 core by commit
> d8c80bb3b55b ("phy: exynos5-usbdrd: Calibrate LOS levels for
> exynos5420/5800"), but it turned out that the mentioned patch worked only
> by the pure luck and fixed only one use case.
>
> PHY calibration was done in DWC3 driver, just before initializing XHCI
> core. This approach was prone to a race. It worked for the fresh boot
> case iff XHCI-plat driver was compiled into the kernel or it's module has
> been loaded before DWC3 probe. In other cases (XHCI-plat module loaded on
> demand after DWC3 probe or during suspend/resume cycle) - the
> calibration was not performed at proper time and had no effect.
>
> This patch creates Exynos5/DWC3 specific variant of XHCI-plat driver,
> which takes care of proper PHY calibration after XHCI core reset, what
> fixes all known use cases (XHCI driver compiled as module and loaded on
> demand as well as during system suspend/resume cycle).
>
> Signed-off-by: Marek Szyprowski <[email protected]>
> ---

Please add my tested on XU4 / XU3 using linux next-20190716
Tested-by: Anand Moon <[email protected]>

Best Regards
-Anand

> drivers/usb/host/Kconfig | 8 ++++++
> drivers/usb/host/Makefile | 3 ++
> drivers/usb/host/xhci-exynos.c | 51 ++++++++++++++++++++++++++++++++++
> drivers/usb/host/xhci-exynos.h | 26 +++++++++++++++++
> drivers/usb/host/xhci-plat.c | 38 ++++++++++++++++++++++++-
> drivers/usb/host/xhci-plat.h | 2 ++
> 6 files changed, 127 insertions(+), 1 deletion(-)
> create mode 100644 drivers/usb/host/xhci-exynos.c
> create mode 100644 drivers/usb/host/xhci-exynos.h
>
> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
> index 40b5de597112..5a17a9b1fbff 100644
> --- a/drivers/usb/host/Kconfig
> +++ b/drivers/usb/host/Kconfig
> @@ -53,6 +53,14 @@ config USB_XHCI_PLATFORM
>
> If unsure, say N.
>
> +config USB_XHCI_EXYNOS
> + tristate "xHCI support for Samsung Exynos SoCs"
> + depends on USB_XHCI_PLATFORM
> + depends on ARCH_EXYNOS || COMPILE_TEST
> + ---help---
> + Say 'Y' to enable the support for the xHCI host controller
> + found in Samsung Exynos ARM SoCs.
> +
> config USB_XHCI_HISTB
> tristate "xHCI support for HiSilicon STB SoCs"
> depends on USB_XHCI_PLATFORM && (ARCH_HISI || COMPILE_TEST)
> diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
> index 84514f71ae44..34afd6680751 100644
> --- a/drivers/usb/host/Makefile
> +++ b/drivers/usb/host/Makefile
> @@ -30,6 +30,9 @@ endif
> ifneq ($(CONFIG_USB_XHCI_RCAR), )
> xhci-plat-hcd-y += xhci-rcar.o
> endif
> +ifneq ($(CONFIG_USB_XHCI_EXYNOS), )
> + xhci-plat-hcd-y += xhci-exynos.o
> +endif
>
> ifneq ($(CONFIG_DEBUG_FS),)
> xhci-hcd-y += xhci-debugfs.o
> diff --git a/drivers/usb/host/xhci-exynos.c b/drivers/usb/host/xhci-exynos.c
> new file mode 100644
> index 000000000000..446d33998382
> --- /dev/null
> +++ b/drivers/usb/host/xhci-exynos.c
> @@ -0,0 +1,51 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * xHCI host controller driver for Samsung Exynos5 SoCs
> + *
> + * Copyright (C) 2019 Samsung Electronics Co., Ltd.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/phy/phy.h>
> +
> +#include "xhci.h"
> +#include "xhci-plat.h"
> +#include "xhci-exynos.h"
> +
> +int xhci_exynos_init_quirk(struct usb_hcd *hcd)
> +{
> + struct xhci_hcd *xhci = hcd_to_xhci(hcd);
> + struct device *dev = hcd->self.controller;
> + struct xhci_plat_priv *xhci_priv = hcd_to_xhci_priv(hcd);
> + struct phy *usb2_generic_phy;
> + int ret;
> +
> + usb2_generic_phy = devm_phy_get(dev->parent, "usb2-phy");
> + if (IS_ERR(usb2_generic_phy)) {
> + ret = PTR_ERR(usb2_generic_phy);
> + if (ret == -EPROBE_DEFER) {
> + return ret;
> + } else {
> + dev_err(dev, "no usb2 phy configured\n");
> + return ret;
> + }
> + }
> +
> + phy_calibrate(usb2_generic_phy);
> + xhci_priv->priv = usb2_generic_phy;
> +
> + xhci->quirks |= XHCI_RESET_ON_RESUME;
> +
> + return 0;
> +}
> +
> +int xhci_exynos_post_resume_quirk(struct usb_hcd *hcd)
> +{
> + struct xhci_plat_priv *xhci_priv = hcd_to_xhci_priv(hcd);
> + struct phy *usb2_generic_phy = xhci_priv->priv;
> +
> + phy_calibrate(usb2_generic_phy);
> +
> + return 0;
> +}
> diff --git a/drivers/usb/host/xhci-exynos.h b/drivers/usb/host/xhci-exynos.h
> new file mode 100644
> index 000000000000..58ea3e9aea8d
> --- /dev/null
> +++ b/drivers/usb/host/xhci-exynos.h
> @@ -0,0 +1,26 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * drivers/usb/host/xhci-exynos.h
> + *
> + * Copyright (C) 2019 Samsung Electronics Co., Ltd.
> + */
> +
> +#ifndef _XHCI_EXYNOS_H
> +#define _XHCI_EXYNOS_H
> +
> +
> +#if IS_ENABLED(CONFIG_USB_XHCI_EXYNOS)
> +int xhci_exynos_init_quirk(struct usb_hcd *hcd);
> +int xhci_exynos_post_resume_quirk(struct usb_hcd *hcd);
> +#else
> +static inline int xhci_exynos_init_quirk(struct usb_hcd *hcd)
> +{
> + return 0;
> +}
> +
> +static inline int xhci_exynos_post_resume_quirk(struct usb_hcd *hcd)
> +{
> + return 0;
> +}
> +#endif
> +#endif /* _XHCI_EXYNOS_H */
> diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
> index 998241f5fce3..6bc03cdb2f21 100644
> --- a/drivers/usb/host/xhci-plat.c
> +++ b/drivers/usb/host/xhci-plat.c
> @@ -24,6 +24,7 @@
> #include "xhci-plat.h"
> #include "xhci-mvebu.h"
> #include "xhci-rcar.h"
> +#include "xhci-exynos.h"
>
> static struct hc_driver __read_mostly xhci_plat_hc_driver;
>
> @@ -64,6 +65,16 @@ static int xhci_priv_resume_quirk(struct usb_hcd *hcd)
> return priv->resume_quirk(hcd);
> }
>
> +static int xhci_priv_post_resume_quirk(struct usb_hcd *hcd)
> +{
> + struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd);
> +
> + if (!priv->post_resume_quirk)
> + return 0;
> +
> + return priv->post_resume_quirk(hcd);
> +}
> +
> static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci)
> {
> /*
> @@ -102,6 +113,11 @@ static const struct xhci_plat_priv xhci_plat_marvell_armada3700 = {
> .init_quirk = xhci_mvebu_a3700_init_quirk,
> };
>
> +static const struct xhci_plat_priv xhci_plat_samsung_exynos5 = {
> + .init_quirk = xhci_exynos_init_quirk,
> + .post_resume_quirk = xhci_exynos_post_resume_quirk,
> +};
> +
> static const struct xhci_plat_priv xhci_plat_renesas_rcar_gen2 = {
> .firmware_name = XHCI_RCAR_FIRMWARE_NAME_V1,
> .init_quirk = xhci_rcar_init_quirk,
> @@ -260,6 +276,13 @@ static int xhci_plat_probe(struct platform_device *pdev)
> goto disable_reg_clk;
>
> priv_match = of_device_get_match_data(&pdev->dev);
> + if (!priv_match) {
> + const struct platform_device_id *id =
> + platform_get_device_id(pdev);
> + if (id)
> + priv_match = (const struct xhci_plat_priv *)
> + id->driver_data;
> + }
> if (priv_match) {
> struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd);
>
> @@ -413,7 +436,11 @@ static int __maybe_unused xhci_plat_resume(struct device *dev)
> if (ret)
> return ret;
>
> - return xhci_resume(xhci, 0);
> + ret = xhci_resume(xhci, 0);
> + if (ret)
> + return ret;
> +
> + return xhci_priv_post_resume_quirk(hcd);
> }
>
> static int __maybe_unused xhci_plat_runtime_suspend(struct device *dev)
> @@ -447,9 +474,18 @@ static const struct acpi_device_id usb_xhci_acpi_match[] = {
> };
> MODULE_DEVICE_TABLE(acpi, usb_xhci_acpi_match);
>
> +static struct platform_device_id xhci_plat_driver_ids[] = {
> + {
> + .name = "exynos5-dwc3-xhci",
> + .driver_data = (long) &xhci_plat_samsung_exynos5,
> + }, { },
> +};
> +MODULE_DEVICE_TABLE(platform, xhci_plat_driver_ids);
> +
> static struct platform_driver usb_xhci_driver = {
> .probe = xhci_plat_probe,
> .remove = xhci_plat_remove,
> + .id_table = xhci_plat_driver_ids,
> .driver = {
> .name = "xhci-hcd",
> .pm = &xhci_plat_pm_ops,
> diff --git a/drivers/usb/host/xhci-plat.h b/drivers/usb/host/xhci-plat.h
> index ae29f22ff5bd..f8a8e84b4ebe 100644
> --- a/drivers/usb/host/xhci-plat.h
> +++ b/drivers/usb/host/xhci-plat.h
> @@ -12,9 +12,11 @@
>
> struct xhci_plat_priv {
> const char *firmware_name;
> + void *priv;
> void (*plat_start)(struct usb_hcd *);
> int (*init_quirk)(struct usb_hcd *);
> int (*resume_quirk)(struct usb_hcd *);
> + int (*post_resume_quirk)(struct usb_hcd *);
> };
>
> #define hcd_to_xhci_priv(h) ((struct xhci_plat_priv *)hcd_to_xhci(h)->priv)
> --
> 2.17.1
>

2019-07-16 17:33:50

by Anand Moon

[permalink] [raw]
Subject: Re: [PATCH 3/3] usb: dwc3: Remove generic PHY calibrate() calls

Hi Marek,

On Thu, 27 Jun 2019 at 12:47, Marek Szyprowski <[email protected]> wrote:
>
> Calls to USB2 generic PHY calibrate() method were added by commit
> d8c80bb3b55b ("phy: exynos5-usbdrd: Calibrate LOS levels for
> exynos5420/5800"), but it turned out that the mentioned patch worked only
> by the pure luck and fixed only one use case. To fix the issues with PHY
> calibration it has been moved to XHCI HCD driver, what allows to perform
> calibration in the proper time window. This patch removes those calls
> from DWC3 driver, as they are no longer needed there.
>
> Signed-off-by: Marek Szyprowski <[email protected]>

Please add my tested on XU4 / XU3 using linux next-20190716
Tested-by: Anand Moon <[email protected]>

Best Regards
-Anand

> ---
> drivers/usb/dwc3/core.c | 2 --
> 1 file changed, 2 deletions(-)
>
> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> index baa029ceede9..f62e8442c614 100644
> --- a/drivers/usb/dwc3/core.c
> +++ b/drivers/usb/dwc3/core.c
> @@ -168,7 +168,6 @@ static void __dwc3_set_mode(struct work_struct *work)
> otg_set_vbus(dwc->usb2_phy->otg, true);
> phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST);
> phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST);
> - phy_calibrate(dwc->usb2_generic_phy);
> }
> break;
> case DWC3_GCTL_PRTCAP_DEVICE:
> @@ -1166,7 +1165,6 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)
> dev_err(dev, "failed to initialize host\n");
> return ret;
> }
> - phy_calibrate(dwc->usb2_generic_phy);
> break;
> case USB_DR_MODE_OTG:
> INIT_WORK(&dwc->drd_work, __dwc3_set_mode);
> --
> 2.17.1
>

2019-07-16 17:34:29

by Anand Moon

[permalink] [raw]
Subject: Re: [PATCH 2/3] usb: dwc3: exynos: Use Exynos specific XHCI-plat driver variant

Hi Marek,

On Thu, 27 Jun 2019 at 12:47, Marek Szyprowski <[email protected]> wrote:
>
> Exynos5 SoCs needs to calibrate USB3.0 DRD PHY after every XHCI HCD
> reset. This patch adds support for instantiating Exynos5-specific variant
> of XHCI-plat driver, which handles the required USB3.0 DRD PHY
> calibration.
>
> Signed-off-by: Marek Szyprowski <[email protected]>
> ---

Please add my tested on XU4 / XU3 using linux next-20190716
Tested-by: Anand Moon <[email protected]>

Best Regards
-Anand

> drivers/usb/dwc3/Kconfig | 1 +
> drivers/usb/dwc3/core.c | 1 +
> drivers/usb/dwc3/core.h | 1 +
> drivers/usb/dwc3/dwc3-exynos.c | 64 +++++++++++++++++++++++-----------
> drivers/usb/dwc3/host.c | 2 +-
> 5 files changed, 47 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
> index 89abc6078703..badf86dfb027 100644
> --- a/drivers/usb/dwc3/Kconfig
> +++ b/drivers/usb/dwc3/Kconfig
> @@ -67,6 +67,7 @@ config USB_DWC3_OMAP
> config USB_DWC3_EXYNOS
> tristate "Samsung Exynos Platform"
> depends on (ARCH_EXYNOS || COMPILE_TEST) && OF
> + select USB_XHCI_EXYNOS if USB_XHCI_PLATFORM
> default USB_DWC3
> help
> Recent Exynos5 SoCs ship with one DesignWare Core USB3 IP inside,
> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> index c9bb93a2c81e..baa029ceede9 100644
> --- a/drivers/usb/dwc3/core.c
> +++ b/drivers/usb/dwc3/core.c
> @@ -1303,6 +1303,7 @@ static void dwc3_get_properties(struct dwc3 *dwc)
> &dwc->hsphy_interface);
> device_property_read_u32(dev, "snps,quirk-frame-length-adjustment",
> &dwc->fladj);
> + device_property_read_string(dev, "snps,xhci_variant", &dwc->hcd_name);
>
> dwc->dis_metastability_quirk = device_property_read_bool(dev,
> "snps,dis_metastability_quirk");
> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> index 3dd783b889cb..1b8f5f5814a4 100644
> --- a/drivers/usb/dwc3/core.h
> +++ b/drivers/usb/dwc3/core.h
> @@ -1176,6 +1176,7 @@ struct dwc3 {
> u8 tx_max_burst_prd;
>
> const char *hsphy_interface;
> + const char *hcd_name;
>
> unsigned connected:1;
> unsigned delayed_status:1;
> diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c
> index c1e9ea621f41..4e847073e85e 100644
> --- a/drivers/usb/dwc3/dwc3-exynos.c
> +++ b/drivers/usb/dwc3/dwc3-exynos.c
> @@ -13,6 +13,7 @@
> #include <linux/slab.h>
> #include <linux/platform_device.h>
> #include <linux/clk.h>
> +#include <linux/dma-mapping.h>
> #include <linux/of.h>
> #include <linux/of_platform.h>
> #include <linux/regulator/consumer.h>
> @@ -35,22 +36,20 @@ struct dwc3_exynos {
>
> struct regulator *vdd33;
> struct regulator *vdd10;
> + struct platform_device *dwc3;
> };
>
> -static int dwc3_exynos_remove_child(struct device *dev, void *unused)
> -{
> - struct platform_device *pdev = to_platform_device(dev);
> -
> - platform_device_unregister(pdev);
> -
> - return 0;
> -}
> +static const struct property_entry dwc3_exynos_properties[] = {
> + PROPERTY_ENTRY_STRING("snps,xhci_variant", "exynos5-dwc3-xhci"),
> + {}
> +};
>
> static int dwc3_exynos_probe(struct platform_device *pdev)
> {
> struct dwc3_exynos *exynos;
> struct device *dev = &pdev->dev;
> - struct device_node *node = dev->of_node;
> + struct device_node *node = dev->of_node, *child;
> + struct platform_device *dwc3;
> const struct dwc3_exynos_driverdata *driver_data;
> int i, ret;
>
> @@ -109,21 +108,43 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
> goto vdd10_err;
> }
>
> - if (node) {
> - ret = of_platform_populate(node, NULL, NULL, dev);
> - if (ret) {
> - dev_err(dev, "failed to add dwc3 core\n");
> - goto populate_err;
> - }
> - } else {
> - dev_err(dev, "no device node, failed to add dwc3 core\n");
> - ret = -ENODEV;
> - goto populate_err;
> + child = of_get_next_child(node, NULL);
> + if (!child) {
> + dev_err(dev, "Failed to find DWC3 core device node\n");
> + goto dwc3_child_err;
> + }
> +
> + dwc3 = of_device_alloc(child, NULL, dev);
> + if (!dwc3) {
> + dev_err(dev, "Failed to allocate DWC3 core device\n");
> + goto dwc3_alloc_err;
> + }
> +
> + dwc3->dev.coherent_dma_mask = DMA_BIT_MASK(32);
> + dwc3->dev.dma_mask = &dwc3->dev.coherent_dma_mask;
> + dwc3->dev.bus = &platform_bus_type;
> +
> + ret = platform_device_add_properties(dwc3, dwc3_exynos_properties);
> + if (ret < 0) {
> + dev_err(dev, "Failed to add properties to DWC3 device\n");
> + goto dwc3_props_err;
> + }
> +
> + ret = of_device_add(dwc3);
> + if (ret) {
> + dev_err(&pdev->dev, "Failed to register DWC3 core device\n");
> + goto dwc3_props_err;
> }
> + exynos->dwc3 = dwc3;
> + of_node_put(child);
>
> return 0;
>
> -populate_err:
> +dwc3_props_err:
> + platform_device_put(dwc3);
> +dwc3_alloc_err:
> + of_node_put(child);
> +dwc3_child_err:
> regulator_disable(exynos->vdd10);
> vdd10_err:
> regulator_disable(exynos->vdd33);
> @@ -142,7 +163,8 @@ static int dwc3_exynos_remove(struct platform_device *pdev)
> struct dwc3_exynos *exynos = platform_get_drvdata(pdev);
> int i;
>
> - device_for_each_child(&pdev->dev, NULL, dwc3_exynos_remove_child);
> + of_device_unregister(exynos->dwc3);
> + platform_device_put(exynos->dwc3);
>
> for (i = exynos->num_clks - 1; i >= 0; i--)
> clk_disable_unprepare(exynos->clks[i]);
> diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
> index f55947294f7c..b526d0c78c3b 100644
> --- a/drivers/usb/dwc3/host.c
> +++ b/drivers/usb/dwc3/host.c
> @@ -71,7 +71,7 @@ int dwc3_host_init(struct dwc3 *dwc)
> dwc->xhci_resources[1].flags = res->flags;
> dwc->xhci_resources[1].name = res->name;
>
> - xhci = platform_device_alloc("xhci-hcd", PLATFORM_DEVID_AUTO);
> + xhci = platform_device_alloc(dwc->hcd_name, PLATFORM_DEVID_AUTO);
> if (!xhci) {
> dev_err(dwc->dev, "couldn't allocate xHCI device\n");
> return -ENOMEM;
> --
> 2.17.1
>