[PATCH] usb: gadget: avoid using gadget after freed
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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