[PATCH] usb: gadget: avoid using gadget after freed

2019-06-14 Thread Lianwei Wang
The udc and gadget device will be deleted when udc device is
disconnected and the related function will be unbind with it.

But if the configfs is not deleted, then the function object
will be kept and the bound status is kept true.

Then after udc device is connected again and a new udc and
gadget objects will be created and passed to bind interface.
But because the bound is still true, the new gadget is not
updated to netdev and a previous freed gadget will be used
in netdev after bind.

To fix this using after freed issue, always set the gadget
object to netdev in bind interface.

Signed-off-by: Lianwei Wang 
---
 drivers/usb/gadget/function/f_ecm.c| 10 ++
 drivers/usb/gadget/function/f_eem.c| 10 ++
 drivers/usb/gadget/function/f_ncm.c| 11 +++
 drivers/usb/gadget/function/f_phonet.c |  2 +-
 drivers/usb/gadget/function/f_rndis.c  |  2 +-
 drivers/usb/gadget/function/f_subset.c | 10 ++
 6 files changed, 27 insertions(+), 18 deletions(-)

diff --git a/drivers/usb/gadget/function/f_ecm.c 
b/drivers/usb/gadget/function/f_ecm.c
index 6ce044008cf6..ff39b7eafec7 100644
--- a/drivers/usb/gadget/function/f_ecm.c
+++ b/drivers/usb/gadget/function/f_ecm.c
@@ -695,15 +695,17 @@ ecm_bind(struct usb_configuration *c, struct usb_function 
*f)
 * with list_for_each_entry, so we assume no race condition
 * with regard to ecm_opts->bound access
 */
+   mutex_lock(&ecm_opts->lock);
+   gether_set_gadget(ecm_opts->net, cdev->gadget);
if (!ecm_opts->bound) {
-   mutex_lock(&ecm_opts->lock);
-   gether_set_gadget(ecm_opts->net, cdev->gadget);
status = gether_register_netdev(ecm_opts->net);
-   mutex_unlock(&ecm_opts->lock);
-   if (status)
+   if (status) {
+   mutex_unlock(&ecm_opts->lock);
return status;
+   }
ecm_opts->bound = true;
}
+   mutex_unlock(&ecm_opts->lock);
 
ecm_string_defs[1].s = ecm->ethaddr;
 
diff --git a/drivers/usb/gadget/function/f_eem.c 
b/drivers/usb/gadget/function/f_eem.c
index c13befa31110..589862dfe1e7 100644
--- a/drivers/usb/gadget/function/f_eem.c
+++ b/drivers/usb/gadget/function/f_eem.c
@@ -256,15 +256,17 @@ static int eem_bind(struct usb_configuration *c, struct 
usb_function *f)
 * with list_for_each_entry, so we assume no race condition
 * with regard to eem_opts->bound access
 */
+   mutex_lock(&eem_opts->lock);
+   gether_set_gadget(eem_opts->net, cdev->gadget);
if (!eem_opts->bound) {
-   mutex_lock(&eem_opts->lock);
-   gether_set_gadget(eem_opts->net, cdev->gadget);
status = gether_register_netdev(eem_opts->net);
-   mutex_unlock(&eem_opts->lock);
-   if (status)
+   if (status) {
+   mutex_unlock(&eem_opts->lock);
return status;
+   }
eem_opts->bound = true;
}
+   mutex_unlock(&eem_opts->lock);
 
us = usb_gstrings_attach(cdev, eem_strings,
 ARRAY_SIZE(eem_string_defs));
diff --git a/drivers/usb/gadget/function/f_ncm.c 
b/drivers/usb/gadget/function/f_ncm.c
index 2d6e76e4cffa..951867e230c2 100644
--- a/drivers/usb/gadget/function/f_ncm.c
+++ b/drivers/usb/gadget/function/f_ncm.c
@@ -1409,15 +1409,18 @@ static int ncm_bind(struct usb_configuration *c, struct 
usb_function *f)
 * with list_for_each_entry, so we assume no race condition
 * with regard to ncm_opts->bound access
 */
+   mutex_lock(&ncm_opts->lock);
+   gether_set_gadget(ncm_opts->net, cdev->gadget);
if (!ncm_opts->bound) {
-   mutex_lock(&ncm_opts->lock);
-   gether_set_gadget(ncm_opts->net, cdev->gadget);
status = gether_register_netdev(ncm_opts->net);
-   mutex_unlock(&ncm_opts->lock);
-   if (status)
+   if (status) {
+   mutex_unlock(&ncm_opts->lock);
goto fail;
+   }
ncm_opts->bound = true;
}
+   mutex_unlock(&ncm_opts->lock);
+
us = usb_gstrings_attach(cdev, ncm_strings,
 ARRAY_SIZE(ncm_string_defs));
if (IS_ERR(us)) {
diff --git a/drivers/usb/gadget/function/f_phonet.c 
b/drivers/usb/gadget/function/f_phonet.c
index 8b72b192c747..e93c5cf95494 100644
--- a/drivers/usb/gadget/function/f_phonet.c
+++ b/drivers/usb/gadget/function/f_phonet.c
@@ -494,8 +494,8 @@ static int pn_bind(struct usb_configuration *c, struct 
usb_function *f)
 * with list_for_each_entry, so we assume no race condition
 * with regard to phonet_opts->bound access
 */
+   gphonet_set_gadget(phonet_opts->net, gadget);
if (!phonet_opts->bound) {
-   gphonet_set_gadget(phonet_op

[PATCH 0/8] Tegra XHCI controller ELPG support

2019-06-14 Thread JC Kuo
Tegra XHCI controler can be placed in ELPG (Engine Level PowerGate)
state for power saving when all of the connected USB devices are in
suspended state. This patch series includes clk, phy and pmc changes
that are required for properly place controller in ELPG and bring
controller out of ELPG.


JC Kuo (8):
  clk: tegra: Add PLLE HW power sequencer control
  clk: tegra: don't enable PLLE HW sequencer at init
  phy: tegra: xusb: t210: rearrange UPHY init
  phy: tegra: xusb: add sleepwalk and suspend/resume
  soc/tegra: pmc: support T210 USB 2.0 Sleepwalk
  phy: tegra: xusb: t210: support wake and sleepwalk
  arm64: tegra: add Tegra210 XUSB PADCTL irq
  xhci: tegra: enable ELPG for runtime/system PM

 arch/arm64/boot/dts/nvidia/tegra210.dtsi |3 +-
 drivers/clk/tegra/clk-pll.c  |   12 -
 drivers/clk/tegra/clk-tegra210.c |   45 +
 drivers/phy/tegra/xusb-tegra210.c| 1023 +-
 drivers/phy/tegra/xusb.c |   80 +-
 drivers/phy/tegra/xusb.h |   10 +
 drivers/soc/tegra/pmc.c  |  462 ++
 drivers/usb/host/xhci-tegra.c|  802 ++---
 include/linux/clk/tegra.h|2 +
 include/linux/phy/tegra/xusb.h   |   12 +
 include/soc/tegra/pmc.h  |   13 +
 11 files changed, 2108 insertions(+), 356 deletions(-)

-- 
2.17.1



[PATCH 4/8] phy: tegra: xusb: add sleepwalk and suspend/resume

2019-06-14 Thread JC Kuo
This commit adds sleepwalk/wake and suspend/resume interfaces
to Tegra XUSB PHY driver.

Signed-off-by: JC Kuo 
---
 drivers/phy/tegra/xusb.c   | 78 ++
 drivers/phy/tegra/xusb.h   |  8 
 include/linux/phy/tegra/xusb.h | 12 ++
 3 files changed, 98 insertions(+)

diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c
index 7fbba53f6097..14461d59b947 100644
--- a/drivers/phy/tegra/xusb.c
+++ b/drivers/phy/tegra/xusb.c
@@ -975,10 +975,36 @@ static int tegra_xusb_padctl_remove(struct 
platform_device *pdev)
return err;
 }
 
+static int tegra_xusb_padctl_suspend_noirq(struct device *dev)
+{
+   struct tegra_xusb_padctl *padctl = dev_get_drvdata(dev);
+
+   if (padctl->soc->ops->suspend_noirq)
+   return padctl->soc->ops->suspend_noirq(padctl);
+
+   return 0;
+}
+
+static int tegra_xusb_padctl_resume_noirq(struct device *dev)
+{
+   struct tegra_xusb_padctl *padctl = dev_get_drvdata(dev);
+
+   if (padctl->soc->ops->resume_noirq)
+   return padctl->soc->ops->resume_noirq(padctl);
+
+   return 0;
+}
+
+static const struct dev_pm_ops tegra_xusb_padctl_pm_ops = {
+   SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(tegra_xusb_padctl_suspend_noirq,
+ tegra_xusb_padctl_resume_noirq)
+};
+
 static struct platform_driver tegra_xusb_padctl_driver = {
.driver = {
.name = "tegra-xusb-padctl",
.of_match_table = tegra_xusb_padctl_of_match,
+   .pm = &tegra_xusb_padctl_pm_ops,
},
.probe = tegra_xusb_padctl_probe,
.remove = tegra_xusb_padctl_remove,
@@ -1045,6 +1071,58 @@ int tegra_xusb_padctl_hsic_set_idle(struct 
tegra_xusb_padctl *padctl,
 }
 EXPORT_SYMBOL_GPL(tegra_xusb_padctl_hsic_set_idle);
 
+int tegra_xusb_padctl_enable_phy_sleepwalk(struct tegra_xusb_padctl *padctl,
+  struct phy *phy,
+  enum usb_device_speed speed)
+{
+   if (padctl->soc->ops->phy_sleepwalk)
+   return padctl->soc->ops->phy_sleepwalk(padctl, phy, true,
+  speed);
+
+   return -ENOTSUPP;
+}
+EXPORT_SYMBOL_GPL(tegra_xusb_padctl_enable_phy_sleepwalk);
+
+int tegra_xusb_padctl_disable_phy_sleepwalk(struct tegra_xusb_padctl *padctl,
+   struct phy *phy)
+{
+   if (padctl->soc->ops->phy_sleepwalk)
+   return padctl->soc->ops->phy_sleepwalk(padctl, phy, false, 0);
+
+   return -ENOTSUPP;
+}
+EXPORT_SYMBOL_GPL(tegra_xusb_padctl_disable_phy_sleepwalk);
+
+int tegra_xusb_padctl_enable_phy_wake(struct tegra_xusb_padctl *padctl,
+ struct phy *phy)
+{
+   if (padctl->soc->ops->phy_wake)
+   return padctl->soc->ops->phy_wake(padctl, phy, true);
+
+   return -ENOTSUPP;
+}
+EXPORT_SYMBOL_GPL(tegra_xusb_padctl_enable_phy_wake);
+
+int tegra_xusb_padctl_disable_phy_wake(struct tegra_xusb_padctl *padctl,
+  struct phy *phy)
+{
+   if (padctl->soc->ops->phy_wake)
+   return padctl->soc->ops->phy_wake(padctl, phy, false);
+
+   return -ENOTSUPP;
+}
+EXPORT_SYMBOL_GPL(tegra_xusb_padctl_disable_phy_wake);
+
+int tegra_xusb_padctl_remote_wake_detected(struct tegra_xusb_padctl *padctl,
+  struct phy *phy)
+{
+   if (padctl->soc->ops->remote_wake_detected)
+   return padctl->soc->ops->remote_wake_detected(phy);
+
+   return -ENOTSUPP;
+}
+EXPORT_SYMBOL_GPL(tegra_xusb_padctl_remote_wake_detected);
+
 int tegra_xusb_padctl_usb3_set_lfps_detect(struct tegra_xusb_padctl *padctl,
   unsigned int port, bool enable)
 {
diff --git a/drivers/phy/tegra/xusb.h b/drivers/phy/tegra/xusb.h
index 1bfe14b2a274..9482914536ac 100644
--- a/drivers/phy/tegra/xusb.h
+++ b/drivers/phy/tegra/xusb.h
@@ -11,6 +11,7 @@
 #include 
 #include 
 
+#include 
 #include 
 
 /* legacy entry points for backwards-compatibility */
@@ -368,12 +369,19 @@ struct tegra_xusb_padctl_ops {
 const struct tegra_xusb_padctl_soc *soc);
void (*remove)(struct tegra_xusb_padctl *padctl);
 
+   int (*suspend_noirq)(struct tegra_xusb_padctl *padctl);
+   int (*resume_noirq)(struct tegra_xusb_padctl *padctl);
int (*usb3_save_context)(struct tegra_xusb_padctl *padctl,
 unsigned int index);
int (*hsic_set_idle)(struct tegra_xusb_padctl *padctl,
 unsigned int index, bool idle);
int (*usb3_set_lfps_detect)(struct tegra_xusb_padctl *padctl,
unsigned int index, bool enable);
+   int (*phy_sleepwalk)(struct tegra_xusb_padctl *padctl, struct phy *phy,
+bool enable, enum usb_device_speed speed);
+   int (*phy_wake)(struc

[PATCH 1/8] clk: tegra: Add PLLE HW power sequencer control

2019-06-14 Thread JC Kuo
PLLE hardware power sequencer has to be enabled after PEX/SATA
UPHY PLL's sequencers are enabled.

tegra210_plle_hw_sequence_start() for XUSB PADCTL driver to enable
PLLE hardware sequencer at proper time.

tegra210_plle_hw_sequence_is_enabled() for XUSB PADCTL driver to
check whether PLLE hardware sequencer has been enabled or not.

Signed-off-by: JC Kuo 
---
 drivers/clk/tegra/clk-tegra210.c | 45 
 include/linux/clk/tegra.h|  2 ++
 2 files changed, 47 insertions(+)

diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c
index e1ba62d2b1a0..14d330669f36 100644
--- a/drivers/clk/tegra/clk-tegra210.c
+++ b/drivers/clk/tegra/clk-tegra210.c
@@ -398,6 +398,14 @@ static const char *mux_pllmcp_clkm[] = {
 #define PLLRE_BASE_DEFAULT_MASK0x1c00
 #define PLLRE_MISC0_WRITE_MASK 0x67ff
 
+/* PLLE */
+#define PLLE_MISC_IDDQ_SW_CTRL (1 << 14)
+#define PLLE_AUX_USE_LOCKDET   (1 << 3)
+#define PLLE_AUX_SS_SEQ_INCLUDE(1 << 31)
+#define PLLE_AUX_ENABLE_SWCTL  (1 << 4)
+#define PLLE_AUX_SS_SWCTL  (1 << 6)
+#define PLLE_AUX_SEQ_ENABLE(1 << 24)
+
 /* PLLX */
 #define PLLX_USE_DYN_RAMP  1
 #define PLLX_BASE_LOCK (1 << 27)
@@ -484,6 +492,43 @@ static const char *mux_pllmcp_clkm[] = {
 #define PLLU_MISC0_WRITE_MASK  0xbfff
 #define PLLU_MISC1_WRITE_MASK  0x0007
 
+bool tegra210_plle_hw_sequence_is_enabled(void)
+{
+   u32 val;
+
+   val = readl_relaxed(clk_base + PLLE_AUX);
+   if (val & PLLE_AUX_SEQ_ENABLE)
+   return true;
+
+   return false;
+}
+EXPORT_SYMBOL_GPL(tegra210_plle_hw_sequence_is_enabled);
+
+void tegra210_plle_hw_sequence_start(void)
+{
+   u32 val;
+
+   if (tegra210_plle_hw_sequence_is_enabled())
+   return;
+
+   val = readl_relaxed(clk_base + PLLE_MISC0);
+   val &= ~PLLE_MISC_IDDQ_SW_CTRL;
+   writel_relaxed(val, clk_base + PLLE_MISC0);
+
+   val = readl_relaxed(clk_base + PLLE_AUX);
+   val |= (PLLE_AUX_USE_LOCKDET | PLLE_AUX_SS_SEQ_INCLUDE);
+   val &= ~(PLLE_AUX_ENABLE_SWCTL | PLLE_AUX_SS_SWCTL);
+   writel_relaxed(val, clk_base + PLLE_AUX);
+
+   fence_udelay(1, clk_base);
+
+   val |= PLLE_AUX_SEQ_ENABLE;
+   writel_relaxed(val, clk_base + PLLE_AUX);
+
+   fence_udelay(1, clk_base);
+}
+EXPORT_SYMBOL_GPL(tegra210_plle_hw_sequence_start);
+
 void tegra210_xusb_pll_hw_control_enable(void)
 {
u32 val;
diff --git a/include/linux/clk/tegra.h b/include/linux/clk/tegra.h
index b8aef62cc3f5..07b6d6145c95 100644
--- a/include/linux/clk/tegra.h
+++ b/include/linux/clk/tegra.h
@@ -110,6 +110,8 @@ static inline void tegra_cpu_clock_resume(void)
 }
 #endif
 
+extern void tegra210_plle_hw_sequence_start(void);
+extern bool tegra210_plle_hw_sequence_is_enabled(void);
 extern void tegra210_xusb_pll_hw_control_enable(void);
 extern void tegra210_xusb_pll_hw_sequence_start(void);
 extern void tegra210_sata_pll_hw_control_enable(void);
-- 
2.17.1



[PATCH 3/8] phy: tegra: xusb: t210: rearrange UPHY init

2019-06-14 Thread JC Kuo
This commit is a preparation for enabling XUSB LP0 support.
It rearranges T210 XUSB PADCTL UPHY initialization sequence,
for the following reasons:

1. PLLE hardware power sequencer has to be enabled only after
   both PEX UPHY PLL and SATA UPHY PLL are initialized.

2. Once UPHY PLL hardware power sequncer is enabled, do not
   assert reset to PEX/SATA PLLs.

3. At LP0 exit, XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN,
   XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN_EARLY, and
   XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_VCORE_DOWN bits have
   to be cleared after XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE
   and XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE bits get set.

4. Move XUSB_PADCTL_SS_PORT_MAP and XUSB_PADCTL_UPHY_USB3_PADX_ECTL*
   registers programming from tegra210_usb3_port_enable() to
   tegra210_pcie_phy_power_on()/tegra210_sata_phy_power_on() so that
   XUSB USB3 ports will be programmed at LP0 exit.

Signed-off-by: JC Kuo 
---
 drivers/phy/tegra/xusb-tegra210.c | 443 ++
 drivers/phy/tegra/xusb.c  |   2 +-
 drivers/phy/tegra/xusb.h  |   2 +
 3 files changed, 264 insertions(+), 183 deletions(-)

diff --git a/drivers/phy/tegra/xusb-tegra210.c 
b/drivers/phy/tegra/xusb-tegra210.c
index 18cea8311d22..007bf352b45e 100644
--- a/drivers/phy/tegra/xusb-tegra210.c
+++ b/drivers/phy/tegra/xusb-tegra210.c
@@ -240,6 +240,8 @@ to_tegra210_xusb_padctl(struct tegra_xusb_padctl *padctl)
return container_of(padctl, struct tegra210_xusb_padctl, base);
 }
 
+static int tegra210_usb3_lane_map(struct tegra_xusb_lane *lane);
+
 /* must be called under padctl->lock */
 static int tegra210_pex_uphy_enable(struct tegra_xusb_padctl *padctl)
 {
@@ -453,35 +455,44 @@ static int tegra210_pex_uphy_enable(struct 
tegra_xusb_padctl *padctl)
 static void tegra210_pex_uphy_disable(struct tegra_xusb_padctl *padctl)
 {
struct tegra_xusb_pcie_pad *pcie = to_pcie_pad(padctl->pcie);
-
-   mutex_lock(&padctl->lock);
+   u32 value;
+   int i;
 
if (WARN_ON(pcie->enable == 0))
-   goto unlock;
+   return;
 
if (--pcie->enable > 0)
-   goto unlock;
+   return;
 
-   reset_control_assert(pcie->rst);
+   for (i = 0; i < padctl->pcie->soc->num_lanes; i++) {
+   value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX);
+   value &= ~XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(i);
+   padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX);
+   }
clk_disable_unprepare(pcie->pll);
-
-unlock:
-   mutex_unlock(&padctl->lock);
 }
 
 /* must be called under padctl->lock */
-static int tegra210_sata_uphy_enable(struct tegra_xusb_padctl *padctl, bool 
usb)
+static int tegra210_sata_uphy_enable(struct tegra_xusb_padctl *padctl)
 {
struct tegra_xusb_sata_pad *sata = to_sata_pad(padctl->sata);
+   struct tegra_xusb_lane *lane = tegra_xusb_find_lane(padctl, "sata", 0);
unsigned long timeout;
u32 value;
int err;
+   bool usb = false;
 
if (sata->enable > 0) {
sata->enable++;
return 0;
}
 
+   if (!lane)
+   return 0;
+
+   if (tegra_xusb_lane_check(lane, "usb3-ss"))
+   usb = true;
+
err = clk_prepare_enable(sata->pll);
if (err < 0)
return err;
@@ -695,30 +706,36 @@ static int tegra210_sata_uphy_enable(struct 
tegra_xusb_padctl *padctl, bool usb)
 static void tegra210_sata_uphy_disable(struct tegra_xusb_padctl *padctl)
 {
struct tegra_xusb_sata_pad *sata = to_sata_pad(padctl->sata);
-
-   mutex_lock(&padctl->lock);
+   u32 value;
+   int i;
 
if (WARN_ON(sata->enable == 0))
-   goto unlock;
+   return;
 
if (--sata->enable > 0)
-   goto unlock;
+   return;
 
-   reset_control_assert(sata->rst);
+   for (i = 0; i < padctl->sata->soc->num_lanes; i++) {
+   value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX);
+   value &= ~XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(i);
+   padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX);
+   }
clk_disable_unprepare(sata->pll);
-
-unlock:
-   mutex_unlock(&padctl->lock);
 }
 
 static int tegra210_xusb_padctl_enable(struct tegra_xusb_padctl *padctl)
 {
-   u32 value;
+   return 0;
+}
 
-   mutex_lock(&padctl->lock);
+static int tegra210_xusb_padctl_disable(struct tegra_xusb_padctl *padctl)
+{
+   return 0;
+}
 
-   if (padctl->enable++ > 0)
-   goto out;
+static void tegra210_aux_mux_lp0_clamp_disable(struct tegra_xusb_padctl 
*padctl)
+{
+   u32 value;
 
value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
value &= ~XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN;
@@ -735,24 +752,12 @@ static int tegra210_xusb_padctl_enable(struct 
tegra_xusb_padctl *padctl)
value = pa

[PATCH 2/8] clk: tegra: don't enable PLLE HW sequencer at init

2019-06-14 Thread JC Kuo
PLLE hardware power sequencer references PEX/SATA UPHY PLL hardware
power sequencers' output to enable/disable PLLE. PLLE hardware power
sequencer has to be enabled only after PEX/SATA UPHY PLL's sequencers
are enabled.

Signed-off-by: JC Kuo 
---
 drivers/clk/tegra/clk-pll.c | 12 
 1 file changed, 12 deletions(-)

diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
index 1583f5fc992f..e6de65987fd2 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -2469,18 +2469,6 @@ static int clk_plle_tegra210_enable(struct clk_hw *hw)
pll_writel(val, PLLE_SS_CTRL, pll);
udelay(1);
 
-   val = pll_readl_misc(pll);
-   val &= ~PLLE_MISC_IDDQ_SW_CTRL;
-   pll_writel_misc(val, pll);
-
-   val = pll_readl(pll->params->aux_reg, pll);
-   val |= (PLLE_AUX_USE_LOCKDET | PLLE_AUX_SS_SEQ_INCLUDE);
-   val &= ~(PLLE_AUX_ENABLE_SWCTL | PLLE_AUX_SS_SWCTL);
-   pll_writel(val, pll->params->aux_reg, pll);
-   udelay(1);
-   val |= PLLE_AUX_SEQ_ENABLE;
-   pll_writel(val, pll->params->aux_reg, pll);
-
 out:
if (pll->lock)
spin_unlock_irqrestore(pll->lock, flags);
-- 
2.17.1



[PATCH 8/8] xhci: tegra: enable ELPG for runtime/system PM

2019-06-14 Thread JC Kuo
This commit enables XUSB host controller ELPG for runtime and system
power management.

NEED CLEANUP.

Signed-off-by: JC Kuo 
---
 drivers/usb/host/xhci-tegra.c | 802 --
 1 file changed, 671 insertions(+), 131 deletions(-)

diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
index 294158113d62..ade56e63212b 100644
--- a/drivers/usb/host/xhci-tegra.c
+++ b/drivers/usb/host/xhci-tegra.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -38,7 +39,17 @@
 #define XUSB_CFG_4 0x010
 #define  XUSB_BASE_ADDR_SHIFT  15
 #define  XUSB_BASE_ADDR_MASK   0x1
+#define XUSB_CFG_160x040
+#define XUSB_CFG_240x060
+#define XUSB_CFG_AXI_CFG   0x0f8
+#define XUSB_CFG_ARU_C11PAGESEL0x404
+#define  XUSB_HSP0 BIT(12)
 #define XUSB_CFG_ARU_C11_CSBRANGE  0x41c
+#define XUSB_CFG_ARU_CONTEXT   0x43c
+#define XUSB_CFG_ARU_CONTEXT_HS_PLS0x478
+#define XUSB_CFG_ARU_CONTEXT_FS_PLS0x47c
+#define XUSB_CFG_ARU_CONTEXT_HSFS_SPEED0x480
+#define XUSB_CFG_ARU_CONTEXT_HSFS_PP   0x484
 #define XUSB_CFG_CSB_BASE_ADDR 0x800
 
 /* FPCI mailbox registers */
@@ -63,11 +74,20 @@
 #define  MBOX_SMI_INTR_EN  BIT(3)
 
 /* IPFS registers */
+#define XUSB_HOST_MSI_BAR_SZ_0 0x0c0
+#define XUSB_HOST_MSI_AXI_BAR_ST_0 0x0c4
+#define XUSB_HOST_MSI_FPCI_BAR_ST_00x0c8
+#define XUSB_HOST_MSI_VEC0_0   0x100
+#define XUSB_HOST_MSI_EN_VEC0_00x140
 #define IPFS_XUSB_HOST_CONFIGURATION_0 0x180
 #define  IPFS_EN_FPCI  BIT(0)
+#define XUSB_HOST_FPCI_ERROR_MASKS_0   0x184
 #define IPFS_XUSB_HOST_INTR_MASK_0 0x188
 #define  IPFS_IP_INT_MASK  BIT(16)
+#define XUSB_HOST_IPFS_INTR_ENABLE_0   0x198
+#define XUSB_HOST_UFPCI_CONFIG_0   0x19c
 #define IPFS_XUSB_HOST_CLKGATE_HYSTERESIS_00x1bc
+#define XUSB_HOST_MCCIF_FIFOCTRL_0 0x1dc
 
 #define CSB_PAGE_SELECT_MASK   0x7f
 #define CSB_PAGE_SELECT_SHIFT  9
@@ -164,6 +184,31 @@ struct tegra_xusb_soc {
bool has_ipfs;
 };
 
+struct tegra_xhci_ipfs_context {
+   u32 msi_bar_sz;
+   u32 msi_axi_barst;
+   u32 msi_fpci_barst;
+   u32 msi_vec0;
+   u32 msi_en_vec0;
+   u32 fpci_error_masks;
+   u32 intr_mask;
+   u32 ipfs_intr_enable;
+   u32 ufpci_config;
+   u32 clkgate_hysteresis;
+   u32 xusb_host_mccif_fifo_cntrl;
+};
+
+struct tegra_xhci_fpci_context {
+   u32 hs_pls;
+   u32 fs_pls;
+   u32 hsfs_speed;
+   u32 hsfs_pp;
+   u32 cfg_aru;
+   u32 cfg_order;
+   u32 cfg_fladj;
+   u32 cfg_sid;
+};
+
 struct tegra_xusb {
struct device *dev;
void __iomem *regs;
@@ -173,6 +218,7 @@ struct tegra_xusb {
 
int xhci_irq;
int mbox_irq;
+   int padctl_irq;
 
void __iomem *ipfs_base;
void __iomem *fpci_base;
@@ -198,8 +244,6 @@ struct tegra_xusb {
 
struct device *genpd_dev_host;
struct device *genpd_dev_ss;
-   struct device_link *genpd_dl_host;
-   struct device_link *genpd_dl_ss;
 
struct phy **phys;
unsigned int num_phys;
@@ -210,9 +254,15 @@ struct tegra_xusb {
void *virt;
dma_addr_t phys;
} fw;
+
+   bool suspended;
+   struct tegra_xhci_fpci_context fpci_ctx;
+   struct tegra_xhci_ipfs_context ipfs_ctx;
 };
 
 static struct hc_driver __read_mostly tegra_xhci_hc_driver;
+static int tegra_xhci_exit_elpg(struct tegra_xusb *tegra, bool runtime);
+static int tegra_xhci_enter_elpg(struct tegra_xusb *tegra, bool runtime);
 
 static inline u32 fpci_readl(struct tegra_xusb *tegra, unsigned int offset)
 {
@@ -585,6 +635,14 @@ static void tegra_xusb_mbox_handle(struct tegra_xusb 
*tegra,
 enable);
if (err < 0)
break;
+
+   if (!enable) {
+   /*
+* Add this delay to increase stability of
+* directing U3.
+*/
+   usleep_range(500, 1000);
+   }
}
 
if (err < 0) {
@@ -621,6 +679,9 @@ static irqreturn_t tegra_xusb_mbox_thread(int irq, void 
*data)
 
mutex_lock(&tegra->lock);
 
+   if (pm_runtime_suspended(tegra->dev) || tegra->suspended)
+   goto out;
+
value = fpci_readl(tegra, XUSB_CFG_ARU_MBOX_DATA_OUT);
tegra_xusb_mbox_unpack(&m

[PATCH 7/8] arm64: tegra: add Tegra210 XUSB PADCTL irq

2019-06-14 Thread JC Kuo
XUSB PADCTL interrupt will be raised when USB wake event happens.
This is required for supporting XUSB host controller ELPG.

Signed-off-by: JC Kuo 
---
 arch/arm64/boot/dts/nvidia/tegra210.dtsi | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
index a550c0a4d572..7496302a1a8a 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
@@ -909,7 +909,8 @@
reg-names = "hcd", "fpci", "ipfs";
 
interrupts = ,
-;
+,
+;
 
clocks = <&tegra_car TEGRA210_CLK_XUSB_HOST>,
 <&tegra_car TEGRA210_CLK_XUSB_HOST_SRC>,
-- 
2.17.1



[PATCH 6/8] phy: tegra: xusb: t210: support wake and sleepwalk

2019-06-14 Thread JC Kuo
This commit implements Tegra210 XUSB PADCTL wake and sleepwalk
routines.

Signed-off-by: JC Kuo 
---
 drivers/phy/tegra/xusb-tegra210.c | 574 --
 1 file changed, 548 insertions(+), 26 deletions(-)

diff --git a/drivers/phy/tegra/xusb-tegra210.c 
b/drivers/phy/tegra/xusb-tegra210.c
index 007bf352b45e..afa4bfa23be8 100644
--- a/drivers/phy/tegra/xusb-tegra210.c
+++ b/drivers/phy/tegra/xusb-tegra210.c
@@ -16,6 +16,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -48,6 +49,20 @@
 #define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(x) (0x7 << ((x) * 5))
 #define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(x, v) (((v) & 0x7) << ((x) * 5))
 
+#define XUSB_PADCTL_ELPG_PROGRAM_0 0x20
+#define   USB2_PORT_WAKE_INTERRUPT_ENABLE(x)  BIT((x))
+#define   USB2_PORT_WAKEUP_EVENT(x)   BIT((x) + 7)
+#define   SS_PORT_WAKE_INTERRUPT_ENABLE(x)BIT((x) + 14)
+#define   SS_PORT_WAKEUP_EVENT(x) BIT((x) + 21)
+#define   USB2_HSIC_PORT_WAKE_INTERRUPT_ENABLE(x) BIT((x) + 28)
+#define   USB2_HSIC_PORT_WAKEUP_EVENT(x)  BIT((x) + 30)
+#define   ALL_WAKE_EVENTS ( \
+   USB2_PORT_WAKEUP_EVENT(0) | USB2_PORT_WAKEUP_EVENT(1) | \
+   USB2_PORT_WAKEUP_EVENT(2) | USB2_PORT_WAKEUP_EVENT(3) | \
+   SS_PORT_WAKEUP_EVENT(0) | SS_PORT_WAKEUP_EVENT(1) | \
+   SS_PORT_WAKEUP_EVENT(2) | SS_PORT_WAKEUP_EVENT(3) | \
+   USB2_HSIC_PORT_WAKEUP_EVENT(0))
+
 #define XUSB_PADCTL_ELPG_PROGRAM1 0x024
 #define XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_VCORE_DOWN (1 << 31)
 #define XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 30)
@@ -81,6 +96,8 @@
 #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR (1 << 2)
 #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_OVRD (1 << 1)
 #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_OVRD (1 << 0)
+#define   RPD_CTRL(x)  (((x) & 0x1f) << 26)
+#define   RPD_CTRL_VALUE(x)(((x) >> 26) & 0x1f)
 
 #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0 0x284
 #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD (1 << 11)
@@ -99,6 +116,8 @@
 #define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_SHIFT 12
 #define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_MASK 0x7f
 #define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_VAL 0x1e
+#define   TCTRL_VALUE(x)(((x) & 0x3f) >> 0)
+#define   PCTRL_VALUE(x)(((x) >> 6) & 0x3f)
 
 #define XUSB_PADCTL_HSIC_PADX_CTL0(x) (0x300 + (x) * 0x20)
 #define XUSB_PADCTL_HSIC_PAD_CTL0_RPU_STROBE (1 << 18)
@@ -228,10 +247,18 @@ struct tegra210_xusb_fuse_calibration {
u32 rpd_ctrl;
 };
 
+struct tegra210_xusb_padctl_context {
+   u32 usb2_pad_mux;
+   u32 usb2_port_cap;
+   u32 ss_port_map;
+   u32 usb3_pad_mux;
+};
+
 struct tegra210_xusb_padctl {
struct tegra_xusb_padctl base;
-
+   struct tegra_utmi_pad_config utmi_pad_cfg;
struct tegra210_xusb_fuse_calibration fuse;
+   struct tegra210_xusb_padctl_context context;
 };
 
 static inline struct tegra210_xusb_padctl *
@@ -868,6 +895,317 @@ static int tegra210_hsic_set_idle(struct 
tegra_xusb_padctl *padctl,
return 0;
 }
 
+static int tegra210_usb3_phy_enable_sleepwalk(struct phy *phy)
+{
+   struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
+   struct tegra_xusb_padctl *padctl = lane->pad->padctl;
+   int index = tegra210_usb3_lane_map(lane);
+   struct device *dev = padctl->dev;
+   u32 reg;
+
+   if (index < 0) {
+   dev_err(dev, "invalid usb3 port number %d\n", index);
+   return -EINVAL;
+   }
+
+   dev_dbg(dev, "phy enable sleepwalk on usb3-%d\n", index);
+
+   mutex_lock(&padctl->lock);
+
+   reg = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
+   reg |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY(index);
+   padctl_writel(padctl, reg, XUSB_PADCTL_ELPG_PROGRAM1);
+
+   usleep_range(100, 200);
+
+   reg = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
+   reg |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN(index);
+   padctl_writel(padctl, reg, XUSB_PADCTL_ELPG_PROGRAM1);
+
+   usleep_range(250, 350);
+
+   mutex_unlock(&padctl->lock);
+
+   return 0;
+}
+
+static void tegra210_utmi_phy_get_pad_config(
+   struct tegra_xusb_padctl *padctl,
+   int port, struct tegra_utmi_pad_config *config)
+{
+   u32 reg;
+
+   reg = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL1);
+   config->tctrl = TCTRL_VALUE(reg);
+   config->pctrl = PCTRL_VALUE(reg);
+
+   reg = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL1(port));
+   config->rpd_ctrl = RPD_CTRL_VALUE(reg);
+}
+
+static int tegra210_usb3_phy_disable_sleepwalk(struct phy *phy)
+{
+   struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
+   struct tegra_xusb_padctl *padctl = lane->pad->padctl;
+   int index = tegra210_usb3_lane_map(lane);
+   struct device *dev =

[PATCH 5/8] soc/tegra: pmc: support T210 USB 2.0 Sleepwalk

2019-06-14 Thread JC Kuo
This commit implements Tegra210 PMC USB 2.0 (UTMI and HSIC) Sleepwalk
programming sequence. With Sleepwalk enabled, XUSB host controller
can be put into ELPG (Engine Level PowerGate) state when controller
is idle to save power. The Sleepwalk logic is in charge of wake event
detection and maintain resume signal accordingly till XUSB host
controller is bring out of ELPG.

Signed-off-by: JC Kuo 
---
 drivers/soc/tegra/pmc.c | 462 
 include/soc/tegra/pmc.h |  13 ++
 2 files changed, 475 insertions(+)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 8878720dd779..8a143cfc83b3 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -142,6 +142,142 @@
 #define  TEGRA_SMC_PMC_READ0xaa
 #define  TEGRA_SMC_PMC_WRITE   0xbb
 
+/* USB2 SLEEPWALK registers */
+#define UTMIP(_port, _offset1, _offset2) \
+   (((_port) <= 2) ? (_offset1) : (_offset2))
+
+#define PMC_UTMIP_UHSIC_SLEEP_CFG(x)   UTMIP(x, 0x1fc, 0x4d0)
+#define   UTMIP_MASTER_ENABLE(x)   UTMIP(x, BIT(8 * (x)), BIT(0))
+#define   UTMIP_FSLS_USE_PMC(x)UTMIP(x, BIT(8 * (x) + 
1), \
+   BIT(1))
+#define   UTMIP_PCTRL_USE_PMC(x)   UTMIP(x, BIT(8 * (x) + 2), \
+   BIT(2))
+#define   UTMIP_TCTRL_USE_PMC(x)   UTMIP(x, BIT(8 * (x) + 3), \
+   BIT(3))
+#define   UTMIP_WAKE_VAL(_port, _value)(((_value) & 0xf) << \
+   (UTMIP(_port, 8 * (_port) + 4, 4)))
+#define   UTMIP_WAKE_VAL_NONE(_port)   UTMIP_WAKE_VAL(_port, 12)
+#define   UTMIP_WAKE_VAL_ANY(_port)UTMIP_WAKE_VAL(_port, 15)
+
+#define PMC_UTMIP_UHSIC_SLEEP_CFG1 (0x4d0)
+#define   UTMIP_RPU_SWITC_LOW_USE_PMC_PX(x)BIT((x) + 8)
+#define   UTMIP_RPD_CTRL_USE_PMC_PX(x) BIT((x) + 16)
+
+#define PMC_UTMIP_MASTER_CONFIG(0x274)
+#define   UTMIP_PWR(x) UTMIP(x, BIT(x), BIT(4))
+#define   UHSIC_PWR(x) BIT(3)
+
+#define PMC_USB_DEBOUNCE_DEL   (0xec)
+#define   DEBOUNCE_VAL(x)  (((x) & 0x) << 0)
+#define   UTMIP_LINE_DEB_CNT(x)(((x) & 0xf) << 16)
+#define   UHSIC_LINE_DEB_CNT(x)(((x) & 0xf) << 20)
+
+#define PMC_UTMIP_UHSIC_FAKE(x)UTMIP(x, 0x218, 0x294)
+#define   UTMIP_FAKE_USBOP_VAL(x)  UTMIP(x, BIT(4 * (x)), BIT(8))
+#define   UTMIP_FAKE_USBON_VAL(x)  UTMIP(x, BIT(4 * (x) + 1), \
+   BIT(9))
+#define   UTMIP_FAKE_USBOP_EN(x)   UTMIP(x, BIT(4 * (x) + 2), \
+   BIT(10))
+#define   UTMIP_FAKE_USBON_EN(x)   UTMIP(x, BIT(4 * (x) + 3), \
+   BIT(11))
+
+#define PMC_UTMIP_UHSIC_SLEEPWALK_CFG(x)   UTMIP(x, 0x200, 0x288)
+#define   UTMIP_LINEVAL_WALK_EN(x) UTMIP(x, BIT(8 * (x) + 7), \
+   BIT(15))
+
+#define PMC_USB_AO (0xf0)
+#define   USBOP_VAL_PD(x)  UTMIP(x, BIT(4 * (x)), BIT(20))
+#define   USBON_VAL_PD(x)  UTMIP(x, BIT(4 * (x) + 1), \
+   BIT(21))
+#define   STROBE_VAL_PD(x) BIT(12)
+#define   DATA0_VAL_PD(x)  BIT(13)
+#define   DATA1_VAL_PD BIT(24)
+
+#define PMC_UTMIP_UHSIC_SAVED_STATE(x) UTMIP(x, 0x1f0, 0x280)
+#define   SPEED(_port, _value) (((_value) & 0x3) << \
+   (UTMIP(_port, 8 * (_port), 8)))
+#define   UTMI_HS(_port)   SPEED(_port, 0)
+#define   UTMI_FS(_port)   SPEED(_port, 1)
+#define   UTMI_LS(_port)   SPEED(_port, 2)
+#define   UTMI_RST(_port)  SPEED(_port, 3)
+
+#define PMC_UTMIP_UHSIC_TRIGGERS   (0x1ec)
+#define   UTMIP_CLR_WALK_PTR(x)UTMIP(x, BIT(x), 
BIT(16))
+#define   UTMIP_CAP_CFG(x) UTMIP(x, BIT((x) + 4), BIT(17))
+#define   UTMIP_CLR_WAKE_ALARM(x)  UTMIP(x, BIT((x) + 12), \
+   BIT(19))
+#define   UHSIC_CLR_WALK_PTR   BIT(3)
+#define   UHSIC_CLR_WAKE_ALARM BIT(15)
+
+#define PMC_UTMIP_SLEEPWALK_PX(x)  UTMIP(x, 0x204 + (4 * (x)), \
+   0x4e0)
+/* phase A */
+#define   UTMIP_USBOP_RPD_ABIT(0)
+#define   UTMIP_USBON_RPD_ABIT(1)
+#define   UTMIP_AP_A   BIT(4)
+#define   UTMIP_AN_A   BIT(5)
+#defin

Re: [PATCH] usb: host: xhci-tegra: Fix Wunused-const-variable

2019-06-14 Thread Thierry Reding
On Thu, Jun 13, 2019 at 11:58:38AM -0700, Nathan Huckleberry wrote:
> Clang produces the following warning
> 
> drivers/usb/host/xhci-tegra.c:357:27: warning: unused variable
> 'mbox_cmd_name' [-Wunused-const-variable]
> static const char * const mbox_cmd_name[] = {
> 
> Looks like it was intended for logging or debugging, but was
> never implemented. Removing mbox_cmd_name.
> 
> Cc: clang-built-li...@googlegroups.com
> Link: https://github.com/ClangBuiltLinux/linux/issues/533
> Signed-off-by: Nathan Huckleberry 
> ---
>  drivers/usb/host/xhci-tegra.c | 23 ---
>  1 file changed, 23 deletions(-)

I wonder why we're not seeing this with regular GCC builds. This code
has been in the kernel for a long time. Oh... looking at the git log, I
see that -Wunused-const-variable was moved to W=1 about 3 years ago, so
these are no longer showing up by default. That would explain it.

Anyway:

Acked-by: Thierry Reding 

> diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
> index 294158113d62..dafc65911fc0 100644
> --- a/drivers/usb/host/xhci-tegra.c
> +++ b/drivers/usb/host/xhci-tegra.c
> @@ -354,29 +354,6 @@ enum tegra_xusb_mbox_cmd {
>   MBOX_CMD_NAK
>  };
>  
> -static const char * const mbox_cmd_name[] = {
> - [  1] = "MSG_ENABLE",
> - [  2] = "INC_FALCON_CLOCK",
> - [  3] = "DEC_FALCON_CLOCK",
> - [  4] = "INC_SSPI_CLOCK",
> - [  5] = "DEC_SSPI_CLOCK",
> - [  6] = "SET_BW",
> - [  7] = "SET_SS_PWR_GATING",
> - [  8] = "SET_SS_PWR_UNGATING",
> - [  9] = "SAVE_DFE_CTLE_CTX",
> - [ 10] = "AIRPLANE_MODE_ENABLED",
> - [ 11] = "AIRPLANE_MODE_DISABLED",
> - [ 12] = "START_HSIC_IDLE",
> - [ 13] = "STOP_HSIC_IDLE",
> - [ 14] = "DBC_WAKE_STACK",
> - [ 15] = "HSIC_PRETEND_CONNECT",
> - [ 16] = "RESET_SSPI",
> - [ 17] = "DISABLE_SS_LFPS_DETECTION",
> - [ 18] = "ENABLE_SS_LFPS_DETECTION",
> - [128] = "ACK",
> - [129] = "NAK",
> -};
> -
>  struct tegra_xusb_mbox_msg {
>   u32 cmd;
>   u32 data;
> -- 
> 2.22.0.rc2.383.gf4fbbf30c2-goog
> 


signature.asc
Description: PGP signature


[PATCH v4 1/8] doc: dt-binding: mxs-usb-phy: add compatible for 7ulp

2019-06-14 Thread Peter Chen
Add compatible for 7ulp USB PHY.

Reviewed-by: Rob Herring 
Signed-off-by: Peter Chen 
---
 Documentation/devicetree/bindings/phy/mxs-usb-phy.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/phy/mxs-usb-phy.txt 
b/Documentation/devicetree/bindings/phy/mxs-usb-phy.txt
index 6ac98b3b5f57..32da8d17759a 100644
--- a/Documentation/devicetree/bindings/phy/mxs-usb-phy.txt
+++ b/Documentation/devicetree/bindings/phy/mxs-usb-phy.txt
@@ -7,6 +7,7 @@ Required properties:
* "fsl,imx6sl-usbphy" for imx6sl
* "fsl,vf610-usbphy" for Vybrid vf610
* "fsl,imx6sx-usbphy" for imx6sx
+   * "fsl,imx7ulp-usbphy" for imx7ulp
   "fsl,imx23-usbphy" is still a fallback for other strings
 - reg: Should contain registers location and length
 - interrupts: Should contain phy interrupt
-- 
2.14.1



[PATCH v4 0/8] Add imx7ulp USBOTG1 support

2019-06-14 Thread Peter Chen
Changes for v4:
- Delete the oldest compatible for usbotg1, usbmisc and usbphy.
[Patch 6/8]

Changes for v3:
- Using readl_poll_timeout to replace private function. [Patch 2/8]
- Add more commit log for new flag CI_HDRC_PMQOS. [Patch 5/8]
- Move 'compatible' at the beginning of propeties. [Patch 6/8]

Changes for v2:
- Use common 'phys' property [Patch 6/8]
- Add the last patch that "fsl,usbphy" phandle is not mandatory now
[Patch 8/8]
- Add Reviewed-by from Rob.


There is a dual-role USB controller at imx7ulp, we add support for it
in this patch set, and the dual-role function is tested at imx7ulp-evk
board.

Thanks.

Peter Chen (8):
  doc: dt-binding: mxs-usb-phy: add compatible for 7ulp
  usb: phy: phy-mxs-usb: add imx7ulp support
  doc: dt-binding: ci-hdrc-usb2: add compatible string for imx7ulp
  doc: dt-binding: usbmisc-imx: add compatible string for imx7ulp
  usb: chipidea: imx: add imx7ulp support
  ARM: dts: imx7ulp: add imx7ulp USBOTG1 support
  ARM: dts: imx7ulp-evk: enable USBOTG1 support
  usb: chipidea: imx: "fsl,usbphy" phandle is not mandatory now

 .../devicetree/bindings/phy/mxs-usb-phy.txt|  1 +
 .../devicetree/bindings/usb/ci-hdrc-usb2.txt   |  1 +
 .../devicetree/bindings/usb/usbmisc-imx.txt|  1 +
 arch/arm/boot/dts/imx7ulp-evk.dts  | 35 +++
 arch/arm/boot/dts/imx7ulp.dtsi | 28 +
 drivers/usb/chipidea/ci_hdrc_imx.c | 33 ++-
 drivers/usb/chipidea/usbmisc_imx.c |  4 ++
 drivers/usb/phy/phy-mxs-usb.c  | 67 +-
 include/linux/usb/chipidea.h   |  1 +
 9 files changed, 167 insertions(+), 4 deletions(-)

-- 
2.14.1



[PATCH v4 5/8] usb: chipidea: imx: add imx7ulp support

2019-06-14 Thread Peter Chen
In this commit, we add CI_HDRC_PMQOS to avoid system entering idle,
at imx7ulp, if the system enters idle, the DMA will stop, so the USB
transfer can't work at this case.

Signed-off-by: Peter Chen 
---
 drivers/usb/chipidea/ci_hdrc_imx.c | 28 +++-
 drivers/usb/chipidea/usbmisc_imx.c |  4 
 include/linux/usb/chipidea.h   |  1 +
 3 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c 
b/drivers/usb/chipidea/ci_hdrc_imx.c
index ceec8d5985d4..a76708501236 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "ci.h"
 #include "ci_hdrc_imx.h"
@@ -63,6 +64,11 @@ static const struct ci_hdrc_imx_platform_flag imx7d_usb_data 
= {
.flags = CI_HDRC_SUPPORTS_RUNTIME_PM,
 };
 
+static const struct ci_hdrc_imx_platform_flag imx7ulp_usb_data = {
+   .flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
+   CI_HDRC_PMQOS,
+};
+
 static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
{ .compatible = "fsl,imx23-usb", .data = &imx23_usb_data},
{ .compatible = "fsl,imx28-usb", .data = &imx28_usb_data},
@@ -72,6 +78,7 @@ static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
{ .compatible = "fsl,imx6sx-usb", .data = &imx6sx_usb_data},
{ .compatible = "fsl,imx6ul-usb", .data = &imx6ul_usb_data},
{ .compatible = "fsl,imx7d-usb", .data = &imx7d_usb_data},
+   { .compatible = "fsl,imx7ulp-usb", .data = &imx7ulp_usb_data},
{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids);
@@ -93,6 +100,8 @@ struct ci_hdrc_imx_data {
struct clk *clk_ahb;
struct clk *clk_per;
/* - */
+   struct pm_qos_request pm_qos_req;
+   const struct ci_hdrc_imx_platform_flag *plat_data;
 };
 
 /* Common functions shared by usbmisc drivers */
@@ -309,6 +318,8 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
if (!data)
return -ENOMEM;
 
+   data->plat_data = imx_platform_flag;
+   pdata.flags |= imx_platform_flag->flags;
platform_set_drvdata(pdev, data);
data->usbmisc_data = usbmisc_get_init_data(dev);
if (IS_ERR(data->usbmisc_data))
@@ -369,6 +380,11 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
}
}
}
+
+   if (pdata.flags & CI_HDRC_PMQOS)
+   pm_qos_add_request(&data->pm_qos_req,
+   PM_QOS_CPU_DMA_LATENCY, 0);
+
ret = imx_get_clks(dev);
if (ret)
goto disable_hsic_regulator;
@@ -396,7 +412,6 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
usb_phy_init(pdata.usb_phy);
}
 
-   pdata.flags |= imx_platform_flag->flags;
if (pdata.flags & CI_HDRC_SUPPORTS_RUNTIME_PM)
data->supports_runtime_pm = true;
 
@@ -439,6 +454,8 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
 disable_hsic_regulator:
if (data->hsic_pad_regulator)
ret = regulator_disable(data->hsic_pad_regulator);
+   if (pdata.flags & CI_HDRC_PMQOS)
+   pm_qos_remove_request(&data->pm_qos_req);
return ret;
 }
 
@@ -455,6 +472,8 @@ static int ci_hdrc_imx_remove(struct platform_device *pdev)
if (data->override_phy_control)
usb_phy_shutdown(data->phy);
imx_disable_unprepare_clks(&pdev->dev);
+   if (data->plat_data->flags & CI_HDRC_PMQOS)
+   pm_qos_remove_request(&data->pm_qos_req);
if (data->hsic_pad_regulator)
regulator_disable(data->hsic_pad_regulator);
 
@@ -480,6 +499,9 @@ static int __maybe_unused imx_controller_suspend(struct 
device *dev)
}
 
imx_disable_unprepare_clks(dev);
+   if (data->plat_data->flags & CI_HDRC_PMQOS)
+   pm_qos_remove_request(&data->pm_qos_req);
+
data->in_lpm = true;
 
return 0;
@@ -497,6 +519,10 @@ static int __maybe_unused imx_controller_resume(struct 
device *dev)
return 0;
}
 
+   if (data->plat_data->flags & CI_HDRC_PMQOS)
+   pm_qos_add_request(&data->pm_qos_req,
+   PM_QOS_CPU_DMA_LATENCY, 0);
+
ret = imx_prepare_enable_clks(dev);
if (ret)
return ret;
diff --git a/drivers/usb/chipidea/usbmisc_imx.c 
b/drivers/usb/chipidea/usbmisc_imx.c
index d8b67e150b12..b7a5727d0c8a 100644
--- a/drivers/usb/chipidea/usbmisc_imx.c
+++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -763,6 +763,10 @@ static const struct of_device_id usbmisc_imx_dt_ids[] = {
.compatible = "fsl,imx7d-usbmisc",
.data = &imx7d_usbmisc_ops,
},
+   {
+   .compatible = "fsl,imx7ulp-usbmisc",
+   .data = &imx7d_usbmisc_ops,
+   },
{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, usbmisc_im

[PATCH v4 6/8] ARM: dts: imx7ulp: add imx7ulp USBOTG1 support

2019-06-14 Thread Peter Chen
Add imx7ulp USBOTG1 support.

Signed-off-by: Peter Chen 
---
 arch/arm/boot/dts/imx7ulp.dtsi | 28 
 1 file changed, 28 insertions(+)

diff --git a/arch/arm/boot/dts/imx7ulp.dtsi b/arch/arm/boot/dts/imx7ulp.dtsi
index fca6e50f37c8..5115e47715c3 100644
--- a/arch/arm/boot/dts/imx7ulp.dtsi
+++ b/arch/arm/boot/dts/imx7ulp.dtsi
@@ -30,6 +30,7 @@
serial1 = &lpuart5;
serial2 = &lpuart6;
serial3 = &lpuart7;
+   usbphy0 = &usbphy1;
};
 
cpus {
@@ -133,6 +134,33 @@
clock-names = "ipg", "per";
};
 
+   usbotg1: usb@4033 {
+   compatible = "fsl,imx7ulp-usb", "fsl,imx6ul-usb";
+   reg = <0x4033 0x200>;
+   interrupts = ;
+   clocks = <&pcc2 IMX7ULP_CLK_USB0>;
+   phys = <&usbphy1>;
+   fsl,usbmisc = <&usbmisc1 0>;
+   ahb-burst-config = <0x0>;
+   tx-burst-size-dword = <0x8>;
+   rx-burst-size-dword = <0x8>;
+   status = "disabled";
+   };
+
+   usbmisc1: usbmisc@40330200 {
+   compatible = "fsl,imx7ulp-usbmisc", "fsl,imx7d-usbmisc";
+   #index-cells = <1>;
+   reg = <0x40330200 0x200>;
+   };
+
+   usbphy1: usbphy@0x4035 {
+   compatible = "fsl,imx7ulp-usbphy", "fsl,imx6ul-usbphy";
+   reg = <0x4035 0x1000>;
+   interrupts = ;
+   clocks = <&pcc2 IMX7ULP_CLK_USB_PHY>;
+   #phy-cells = <0>;
+   };
+
usdhc0: mmc@4037 {
compatible = "fsl,imx7ulp-usdhc", "fsl,imx6sx-usdhc";
reg = <0x4037 0x1>;
-- 
2.14.1



[PATCH v4 3/8] doc: dt-binding: ci-hdrc-usb2: add compatible string for imx7ulp

2019-06-14 Thread Peter Chen
Add compatible string for imx7ulp.

Reviewed-by: Rob Herring 
Signed-off-by: Peter Chen 
---
 Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt 
b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
index a254386a91ad..cfc9f40ab641 100644
--- a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
+++ b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
@@ -10,6 +10,7 @@ Required properties:
"fsl,imx6sx-usb"
"fsl,imx6ul-usb"
"fsl,imx7d-usb"
+   "fsl,imx7ulp-usb"
"lsi,zevio-usb"
"qcom,ci-hdrc"
"chipidea,usb2"
-- 
2.14.1



[PATCH v4 7/8] ARM: dts: imx7ulp-evk: enable USBOTG1 support

2019-06-14 Thread Peter Chen
Enable USBOTG1 support for evk board, it is dual-role function
port.

Signed-off-by: Peter Chen 
---
 arch/arm/boot/dts/imx7ulp-evk.dts | 35 +++
 1 file changed, 35 insertions(+)

diff --git a/arch/arm/boot/dts/imx7ulp-evk.dts 
b/arch/arm/boot/dts/imx7ulp-evk.dts
index a09026a6d22e..c8a56a2ae9a5 100644
--- a/arch/arm/boot/dts/imx7ulp-evk.dts
+++ b/arch/arm/boot/dts/imx7ulp-evk.dts
@@ -22,6 +22,17 @@
reg = <0x6000 0x4000>;
};
 
+   reg_usb_otg1_vbus: regulator-usb-otg1-vbus {
+   compatible = "regulator-fixed";
+   pinctrl-names = "default";
+   pinctrl-0 = <&pinctrl_usbotg1_vbus>;
+   regulator-name = "usb_otg1_vbus";
+   regulator-min-microvolt = <500>;
+   regulator-max-microvolt = <500>;
+   gpio = <&gpio_ptc 0 GPIO_ACTIVE_HIGH>;
+   enable-active-high;
+   };
+
reg_vsd_3v3: regulator-vsd-3v3 {
compatible = "regulator-fixed";
regulator-name = "VSD_3V3";
@@ -40,6 +51,17 @@
status = "okay";
 };
 
+&usbotg1 {
+   vbus-supply = <®_usb_otg1_vbus>;
+   pinctrl-names = "default";
+   pinctrl-0 = <&pinctrl_usbotg1_id>;
+   srp-disable;
+   hnp-disable;
+   adp-disable;
+   over-current-active-low;
+   status = "okay";
+};
+
 &usdhc0 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc0>;
@@ -57,6 +79,19 @@
bias-pull-up;
};
 
+   pinctrl_usbotg1_vbus: otg1vbusgrp {
+   fsl,pins = <
+   IMX7ULP_PAD_PTC0__PTC0  0x2
+   >;
+   };
+
+   pinctrl_usbotg1_id: otg1idgrp {
+   fsl,pins = <
+   IMX7ULP_PAD_PTC13__USB0_ID  0x10003
+   IMX7ULP_PAD_PTC16__USB1_OC2 0x10003
+   >;
+   };
+
pinctrl_usdhc0: usdhc0grp {
fsl,pins = <
IMX7ULP_PAD_PTD1__SDHC0_CMD 0x43
-- 
2.14.1



[PATCH v4 4/8] doc: dt-binding: usbmisc-imx: add compatible string for imx7ulp

2019-06-14 Thread Peter Chen
Add compatible string for imx7ulp

Reviewed-by: Rob Herring 
Signed-off-by: Peter Chen 
---
 Documentation/devicetree/bindings/usb/usbmisc-imx.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/usb/usbmisc-imx.txt 
b/Documentation/devicetree/bindings/usb/usbmisc-imx.txt
index a85a631ec434..b353b9816487 100644
--- a/Documentation/devicetree/bindings/usb/usbmisc-imx.txt
+++ b/Documentation/devicetree/bindings/usb/usbmisc-imx.txt
@@ -7,6 +7,7 @@ Required properties:
"fsl,vf610-usbmisc" for Vybrid vf610
"fsl,imx6sx-usbmisc" for imx6sx
"fsl,imx7d-usbmisc" for imx7d
+   "fsl,imx7ulp-usbmisc" for imx7ulp
 - reg: Should contain registers location and length
 
 Examples:
-- 
2.14.1



[PATCH v4 2/8] usb: phy: phy-mxs-usb: add imx7ulp support

2019-06-14 Thread Peter Chen
At imx7ulp, the USB related analog register is located in PHY register
region too, so we need to control PLL at PHY driver directly.

Signed-off-by: Peter Chen 
---
 drivers/usb/phy/phy-mxs-usb.c | 67 ++-
 1 file changed, 66 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c
index 1b1bb0ad40c3..183467f74fe1 100644
--- a/drivers/usb/phy/phy-mxs-usb.c
+++ b/drivers/usb/phy/phy-mxs-usb.c
@@ -17,9 +17,11 @@
 #include 
 #include 
 #include 
+#include 
 
 #define DRIVER_NAME "mxs_phy"
 
+/* Register Macro */
 #define HW_USBPHY_PWD  0x00
 #define HW_USBPHY_TX   0x10
 #define HW_USBPHY_CTRL 0x30
@@ -37,6 +39,11 @@
 #define GM_USBPHY_TX_TXCAL45DN(x)(((x) & 0xf) << 8)
 #define GM_USBPHY_TX_D_CAL(x)(((x) & 0xf) << 0)
 
+/* imx7ulp */
+#define HW_USBPHY_PLL_SIC  0xa0
+#define HW_USBPHY_PLL_SIC_SET  0xa4
+#define HW_USBPHY_PLL_SIC_CLR  0xa8
+
 #define BM_USBPHY_CTRL_SFTRST  BIT(31)
 #define BM_USBPHY_CTRL_CLKGATE BIT(30)
 #define BM_USBPHY_CTRL_OTG_ID_VALUEBIT(27)
@@ -55,6 +62,12 @@
 #define BM_USBPHY_IP_FIX   (BIT(17) | BIT(18))
 
 #define BM_USBPHY_DEBUG_CLKGATEBIT(30)
+/* imx7ulp */
+#define BM_USBPHY_PLL_LOCK BIT(31)
+#define BM_USBPHY_PLL_REG_ENABLE   BIT(21)
+#define BM_USBPHY_PLL_BYPASS   BIT(16)
+#define BM_USBPHY_PLL_POWERBIT(12)
+#define BM_USBPHY_PLL_EN_USB_CLKS  BIT(6)
 
 /* Anatop Registers */
 #define ANADIG_ANA_MISC0   0x150
@@ -167,6 +180,9 @@ static const struct mxs_phy_data imx6ul_phy_data = {
.flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS,
 };
 
+static const struct mxs_phy_data imx7ulp_phy_data = {
+};
+
 static const struct of_device_id mxs_phy_dt_ids[] = {
{ .compatible = "fsl,imx6sx-usbphy", .data = &imx6sx_phy_data, },
{ .compatible = "fsl,imx6sl-usbphy", .data = &imx6sl_phy_data, },
@@ -174,6 +190,7 @@ static const struct of_device_id mxs_phy_dt_ids[] = {
{ .compatible = "fsl,imx23-usbphy", .data = &imx23_phy_data, },
{ .compatible = "fsl,vf610-usbphy", .data = &vf610_phy_data, },
{ .compatible = "fsl,imx6ul-usbphy", .data = &imx6ul_phy_data, },
+   { .compatible = "fsl,imx7ulp-usbphy", .data = &imx7ulp_phy_data, },
{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, mxs_phy_dt_ids);
@@ -198,6 +215,11 @@ static inline bool is_imx6sl_phy(struct mxs_phy *mxs_phy)
return mxs_phy->data == &imx6sl_phy_data;
 }
 
+static inline bool is_imx7ulp_phy(struct mxs_phy *mxs_phy)
+{
+   return mxs_phy->data == &imx7ulp_phy_data;
+}
+
 /*
  * PHY needs some 32K cycles to switch from 32K clock to
  * bus (such as AHB/AXI, etc) clock.
@@ -221,14 +243,49 @@ static void mxs_phy_tx_init(struct mxs_phy *mxs_phy)
}
 }
 
+static int mxs_phy_pll_enable(void __iomem *base, bool enable)
+{
+   int ret = 0;
+
+   if (enable) {
+   u32 value;
+
+   writel(BM_USBPHY_PLL_REG_ENABLE, base + HW_USBPHY_PLL_SIC_SET);
+   writel(BM_USBPHY_PLL_BYPASS, base + HW_USBPHY_PLL_SIC_CLR);
+   writel(BM_USBPHY_PLL_POWER, base + HW_USBPHY_PLL_SIC_SET);
+   ret = readl_poll_timeout(base + HW_USBPHY_PLL_SIC,
+   value, (value & BM_USBPHY_PLL_LOCK) != 0,
+   100, 1);
+   if (ret)
+   return ret;
+
+   writel(BM_USBPHY_PLL_EN_USB_CLKS, base +
+   HW_USBPHY_PLL_SIC_SET);
+   } else {
+   writel(BM_USBPHY_PLL_EN_USB_CLKS, base +
+   HW_USBPHY_PLL_SIC_CLR);
+   writel(BM_USBPHY_PLL_POWER, base + HW_USBPHY_PLL_SIC_CLR);
+   writel(BM_USBPHY_PLL_BYPASS, base + HW_USBPHY_PLL_SIC_SET);
+   writel(BM_USBPHY_PLL_REG_ENABLE, base + HW_USBPHY_PLL_SIC_CLR);
+   }
+
+   return ret;
+}
+
 static int mxs_phy_hw_init(struct mxs_phy *mxs_phy)
 {
int ret;
void __iomem *base = mxs_phy->phy.io_priv;
 
+   if (is_imx7ulp_phy(mxs_phy)) {
+   ret = mxs_phy_pll_enable(base, true);
+   if (ret)
+   return ret;
+   }
+
ret = stmp_reset_block(base + HW_USBPHY_CTRL);
if (ret)
-   return ret;
+   goto disable_pll;
 
/* Power up the PHY */
writel(0, base + HW_USBPHY_PWD);
@@ -253,6 +310,11 @@ static int mxs_phy_hw_init(struct mxs_phy *mxs_phy)
mxs_phy_tx_init(mxs_phy);
 
return 0;
+
+disable_pll:
+   if (is_imx7ulp_phy(mxs_phy))
+   mxs_phy_pll_enable(base, false);
+   return ret;
 }
 
 /* Return true if the vbus is there */
@@ -374,6 +436,9 @@ stat

[PATCH v4 8/8] usb: chipidea: imx: "fsl,usbphy" phandle is not mandatory now

2019-06-14 Thread Peter Chen
Since the chipidea common code support get the USB PHY phandle from
"phys", the glue layer is not mandatory to get the "fsl,usbphy" phandle
any more.

Signed-off-by: Peter Chen 
---
 drivers/usb/chipidea/ci_hdrc_imx.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c 
b/drivers/usb/chipidea/ci_hdrc_imx.c
index a76708501236..b5abfe89190c 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -398,8 +398,9 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
ret = PTR_ERR(data->phy);
/* Return -EINVAL if no usbphy is available */
if (ret == -ENODEV)
-   ret = -EINVAL;
-   goto err_clk;
+   data->phy = NULL;
+   else
+   goto err_clk;
}
 
pdata.usb_phy = data->phy;
-- 
2.14.1



Re: [PATCH] usb: xhci: dbc: get rid of global pointer

2019-06-14 Thread Mathias Nyman

On 11.6.2019 20.24, Felipe Balbi wrote:

If we happen to have two XHCI controllers with DbC capability, then
there's no hope this will ever work as the global pointer will be
overwritten by the controller that probes last.

Avoid this problem by keeping the tty_driver struct pointer inside
struct xhci_dbc.

Fixes: dfba2174dc42 usb: xhci: Add DbC support in xHCI driver
Cc:  # v4.16+
Signed-off-by: Felipe Balbi 
---


Thanks, adding to queue

-Mathias


Re: [PATCH] usb: xhci: dbc: get rid of global pointer

2019-06-14 Thread Johan Hovold
On Tue, Jun 11, 2019 at 08:24:16PM +0300, Felipe Balbi wrote:
> If we happen to have two XHCI controllers with DbC capability, then
> there's no hope this will ever work as the global pointer will be
> overwritten by the controller that probes last.
> 
> Avoid this problem by keeping the tty_driver struct pointer inside
> struct xhci_dbc.

How did you test this patch?

> Fixes: dfba2174dc42 usb: xhci: Add DbC support in xHCI driver
> Cc:  # v4.16+
> Signed-off-by: Felipe Balbi 
> ---
>  drivers/usb/host/xhci-dbgcap.c |  4 +--
>  drivers/usb/host/xhci-dbgcap.h |  3 +-
>  drivers/usb/host/xhci-dbgtty.c | 54 +-
>  3 files changed, 31 insertions(+), 30 deletions(-)
> 
> diff --git a/drivers/usb/host/xhci-dbgcap.c b/drivers/usb/host/xhci-dbgcap.c
> index 52e32644a4b2..5f56b650c0ea 100644
> --- a/drivers/usb/host/xhci-dbgcap.c
> +++ b/drivers/usb/host/xhci-dbgcap.c
> @@ -948,7 +948,7 @@ int xhci_dbc_init(struct xhci_hcd *xhci)
>   return 0;
>  
>  init_err1:
> - xhci_dbc_tty_unregister_driver();
> + xhci_dbc_tty_unregister_driver(xhci);
>  init_err2:
>   xhci_do_dbc_exit(xhci);
>  init_err3:
> @@ -963,7 +963,7 @@ void xhci_dbc_exit(struct xhci_hcd *xhci)
>   return;
>  
>   device_remove_file(dev, &dev_attr_dbc);
> - xhci_dbc_tty_unregister_driver();
> + xhci_dbc_tty_unregister_driver(xhci);
>   xhci_dbc_stop(xhci);
>   xhci_do_dbc_exit(xhci);
>  }
> diff --git a/drivers/usb/host/xhci-dbgcap.h b/drivers/usb/host/xhci-dbgcap.h
> index ce0c6072bd48..30dedf36c566 100644
> --- a/drivers/usb/host/xhci-dbgcap.h
> +++ b/drivers/usb/host/xhci-dbgcap.h
> @@ -151,6 +151,7 @@ struct xhci_dbc {
>   struct dbc_ep   eps[2];
>  
>   struct dbc_port port;
> + struct tty_driver   *tty_driver;
>  };
>  
>  #define dbc_bulkout_ctx(d)   \
> @@ -196,7 +197,7 @@ static inline struct dbc_ep *get_out_ep(struct xhci_hcd 
> *xhci)
>  int xhci_dbc_init(struct xhci_hcd *xhci);
>  void xhci_dbc_exit(struct xhci_hcd *xhci);
>  int xhci_dbc_tty_register_driver(struct xhci_hcd *xhci);
> -void xhci_dbc_tty_unregister_driver(void);
> +void xhci_dbc_tty_unregister_driver(struct xhci_hcd *xhci);
>  int xhci_dbc_tty_register_device(struct xhci_hcd *xhci);
>  void xhci_dbc_tty_unregister_device(struct xhci_hcd *xhci);
>  struct dbc_request *dbc_alloc_request(struct dbc_ep *dep, gfp_t gfp_flags);
> diff --git a/drivers/usb/host/xhci-dbgtty.c b/drivers/usb/host/xhci-dbgtty.c
> index aff79ff5aba4..300fc770a0d5 100644
> --- a/drivers/usb/host/xhci-dbgtty.c
> +++ b/drivers/usb/host/xhci-dbgtty.c
> @@ -279,52 +279,52 @@ static const struct tty_operations dbc_tty_ops = {
>   .unthrottle = dbc_tty_unthrottle,
>  };
>  
> -static struct tty_driver *dbc_tty_driver;
> -
>  int xhci_dbc_tty_register_driver(struct xhci_hcd *xhci)
>  {
>   int status;
>   struct xhci_dbc *dbc = xhci->dbc;
>  
> - dbc_tty_driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW |
> + dbc->tty_driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW |
> TTY_DRIVER_DYNAMIC_DEV);
> - if (IS_ERR(dbc_tty_driver)) {
> - status = PTR_ERR(dbc_tty_driver);
> - dbc_tty_driver = NULL;
> + if (IS_ERR(dbc->tty_driver)) {
> + status = PTR_ERR(dbc->tty_driver);
> + dbc->tty_driver = NULL;
>   return status;
>   }
>  
> - dbc_tty_driver->driver_name = "dbc_serial";
> - dbc_tty_driver->name = "ttyDBC";
> + dbc->tty_driver->driver_name = "dbc_serial";
> + dbc->tty_driver->name = "ttyDBC";

You're now registering multiple drivers for the same thing (and wasting
a major number for each) and specifically using the same name, which
should lead to name clashes when registering the second port.

Possibly better than the current situation, but why not fix this
properly instead? Register the driver once, and just pick a new minor
number for each controller.

> - dbc_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
> - dbc_tty_driver->subtype = SERIAL_TYPE_NORMAL;
> - dbc_tty_driver->init_termios = tty_std_termios;
> - dbc_tty_driver->init_termios.c_cflag =
> + dbc->tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
> + dbc->tty_driver->subtype = SERIAL_TYPE_NORMAL;
> + dbc->tty_driver->init_termios = tty_std_termios;
> + dbc->tty_driver->init_termios.c_cflag =
>   B9600 | CS8 | CREAD | HUPCL | CLOCAL;
> - dbc_tty_driver->init_termios.c_ispeed = 9600;
> - dbc_tty_driver->init_termios.c_ospeed = 9600;
> - dbc_tty_driver->driver_state = &dbc->port;
> + dbc->tty_driver->init_termios.c_ispeed = 9600;
> + dbc->tty_driver->init_termios.c_ospeed = 9600;
> + dbc->tty_driver->driver_state = &dbc->port;
>  
> - tty_set_operations(dbc_tty_driver, &dbc_tty_ops);
> + tty_set_operations(dbc->tty_driver, &dbc_tty_ops);
>  
> - status = tty

DWC3 USB hub issue

2019-06-14 Thread Manivannan Sadhasivam
Hello,

I'm trying to upstream Designware USB3 host driver present in the Actions
Semi S900 SoC. It can successfully detect the USB hub but when any of the
USB device got plugged in, it fails with following error:

[4.365566] usb usb1-port1: connect-debounce failed

Full log can be found here: https://pastebin.ubuntu.com/p/PNff5fZkn6/

Below is the output of, lsusb -v:

Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Device Descriptor:
  bLength18
  bDescriptorType 1
  bcdUSB   3.00
  bDeviceClass9 Hub
  bDeviceSubClass 0 Unused
  bDeviceProtocol 3 
  bMaxPacketSize0 9
  idVendor   0x1d6b Linux Foundation
  idProduct  0x0003 3.0 root hub
  bcdDevice5.02
  iManufacturer   3 Linux 5.2.0-rc3-00032-gbd970cfc7a82-dirty xhci-hcd
  iProduct2 xHCI Host Controller
  iSerial 1 xhci-hcd.0.auto
  bNumConfigurations  1
  Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength   31
bNumInterfaces  1
bConfigurationValue 1
iConfiguration  0 
bmAttributes 0xe0
  Self Powered
  Remote Wakeup
MaxPower0mA
Interface Descriptor:
  bLength 9
  bDescriptorType 4
  bInterfaceNumber0
  bAlternateSetting   0
  bNumEndpoints   1
  bInterfaceClass 9 Hub
  bInterfaceSubClass  0 Unused
  bInterfaceProtocol  0 Full speed (or root) hub
  iInterface  0 
  Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81  EP 1 IN
bmAttributes3
  Transfer TypeInterrupt
  Synch Type   None
  Usage Type   Data
wMaxPacketSize 0x0004  1x 4 bytes
bInterval  12
bMaxBurst   0
Hub Descriptor:
  bLength  12
  bDescriptorType  42
  nNbrPorts 1
  wHubCharacteristic 0x000a
No power switching (usb 1.0)
Per-port overcurrent protection
  bPwrOn2PwrGood   10 * 2 milli seconds
  bHubContrCurrent  0 milli Ampere
  bHubDecLat  0.0 micro seconds
  wHubDelay 0 nano seconds
  DeviceRemovable0x00
 Hub Port Status:
   Port 1: .02a0 5Gbps power Rx.Detect
Binary Object Store Descriptor:
  bLength 5
  bDescriptorType15
  wTotalLength   15
  bNumDeviceCaps  1
  SuperSpeed USB Device Capability:
bLength10
bDescriptorType16
bDevCapabilityType  3
bmAttributes 0x02
  Latency Tolerance Messages (LTM) Supported
wSpeedsSupported   0x0008
  Device can operate at SuperSpeed (5Gbps)
bFunctionalitySupport   3
  Lowest fully-functional device speed is SuperSpeed (5Gbps)
bU1DevExitLat   0 micro seconds
bU2DevExitLat   0 micro seconds
Device Status: 0x0001
  Self Powered

Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Devicetree snippet:

usbdrd3_0: usb@e040 {
compatible = "actions,s900-dwc3";
clocks = <&cmu CLK_USB3_480MPLL0>,
 <&cmu CLK_USB3_480MPHY0>,
 <&cmu CLK_USB3_5GPHY>,
 <&cmu CLK_USB3_CCE>,
 <&cmu CLK_USB3_MAC>;
clock-names = "usb3_480mpll0", "usb3_480mphy0",
  "usb3_5gphy", "usb3_cce",
  "usb3_mac";
resets  = <&cmu RESET_USB3>;
reset-names = "usb3";
power-domains = <&sps S900_PD_USB3>;
#address-cells = <2>;
#size-cells = <2>;
ranges;

usbdrd_dwc3_0: dwc3 {
compatible = "snps,dwc3";
reg = <0x0 0xe040 0x0 0x10>;
interrupts = ;
usb-phy = <&usb2_phy>, <&usb3_phy>;
dr_mode = "host";
power-domains = <&sps S900_PD_USB3>;
snps,hsphy_interface = "utmi";
};
};

After going through the mailing list looking for similar issue, found that
some host controllers works with following quirk:

snps,dis_u3_susphy_quirk;

I tried that also but it didn't work. Can anyone shed some light on this?

PS: USB3 is working fine with vendor kernel 3.10.

Thanks,
Mani