Merge "usb: phy-msm-ssusb-qmp: Perform USB only reset in USB+DP mode"

This commit is contained in:
qctecmdr 2021-04-19 01:39:21 -07:00 • committed by Gerrit - the friendly Code Review server
commit 603aeb2ca6
3 changed files with 54 additions and 12 deletions

View file

@ -4423,7 +4423,7 @@ static void dwc3_start_stop_device(struct dwc3_msm *mdwc, bool start)
dbg_log_string("stop_device_mode completed");
}
int dwc3_msm_release_ss_lane(struct device *dev)
int dwc3_msm_release_ss_lane(struct device *dev, bool usb_dp_concurrent_mode)
{
struct dwc3_msm *mdwc = dev_get_drvdata(dev);
struct dwc3 *dwc = NULL;
@ -4439,6 +4439,16 @@ int dwc3_msm_release_ss_lane(struct device *dev)
return -EAGAIN;
}
/*
* If the MPA connected is multi_func capable set the flag assuming
* that USB and DP is operating in concurrent mode and bail out early.
*/
if (usb_dp_concurrent_mode) {
mdwc->ss_phy->flags |= PHY_USB_DP_CONCURRENT_MODE;
dbg_event(0xFF, "USB_DP_CONCURRENT_MODE", 1);
return 0;
}
dbg_event(0xFF, "ss_lane_release", 0);
/* flush any pending work */
flush_work(&mdwc->resume_work);
@ -5244,6 +5254,7 @@ static int dwc3_otg_start_host(struct dwc3_msm *mdwc, int on)
USB_SPEED_SUPER);
usb_phy_notify_disconnect(mdwc->ss_phy,
USB_SPEED_SUPER);
mdwc->ss_phy->flags &= ~PHY_USB_DP_CONCURRENT_MODE;
}
redriver_notify_disconnect(mdwc->ss_redriver_node);
@ -5365,6 +5376,7 @@ static int dwc3_otg_start_peripheral(struct dwc3_msm *mdwc, int on)
usb_phy_notify_disconnect(mdwc->hs_phy, USB_SPEED_HIGH);
usb_phy_notify_disconnect(mdwc->ss_phy, USB_SPEED_SUPER);
redriver_notify_disconnect(mdwc->ss_redriver_node);
mdwc->ss_phy->flags &= ~PHY_USB_DP_CONCURRENT_MODE;
dwc3_override_vbus_status(mdwc, false);
dwc3_msm_write_reg_field(mdwc->base, DWC3_GUSB3PIPECTL(0),
DWC3_GUSB3PIPECTL_SUSPHY, 0);

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2013-2021, The Linux Foundation. All rights reserved.
*/
#include <linux/module.h>
@ -405,9 +405,11 @@ static void usb_qmp_update_portselect_phymode(struct msm_ssphy_qmp *phy)
}
/* override hardware control for reset of qmp phy */
writel_relaxed(SW_DPPHY_RESET_MUX | SW_DPPHY_RESET |
SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET,
phy->base + phy->phy_reg[USB3_DP_COM_RESET_OVRD_CTRL]);
if (!(phy->phy.flags & PHY_USB_DP_CONCURRENT_MODE))
writel_relaxed(SW_DPPHY_RESET_MUX | SW_DPPHY_RESET |
SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET,
phy->base +
phy->phy_reg[USB3_DP_COM_RESET_OVRD_CTRL]);
/* update port select */
if (val > 0) {
@ -417,11 +419,13 @@ static void usb_qmp_update_portselect_phymode(struct msm_ssphy_qmp *phy)
phy->phy_reg[USB3_DP_COM_TYPEC_CTRL]);
}
msm_ssphy_qmp_setmode(phy, USB3_DP_COMBO_MODE);
if (!(phy->phy.flags & PHY_USB_DP_CONCURRENT_MODE)) {
msm_ssphy_qmp_setmode(phy, USB3_DP_COMBO_MODE);
/* bring both USB and DP PHYs PCS block out of reset */
writel_relaxed(0x00, phy->base +
phy->phy_reg[USB3_DP_COM_RESET_OVRD_CTRL]);
/* bring both USB and DP PHYs PCS block out of reset */
writel_relaxed(0x00, phy->base +
phy->phy_reg[USB3_DP_COM_RESET_OVRD_CTRL]);
}
break;
case USB3_OR_DP:
if (val > 0) {
@ -513,6 +517,12 @@ static int msm_ssphy_qmp_init(struct usb_phy *uphy)
goto fail;
}
/* perform software reset of PHY common logic */
if (phy->phy_type == USB3_AND_DP &&
!(phy->phy.flags & PHY_USB_DP_CONCURRENT_MODE))
writel_relaxed(0x00,
phy->base + phy->phy_reg[USB3_DP_COM_SW_RESET]);
/* perform software reset of PCS/Serdes */
writel_relaxed(0x00, phy->base + phy->phy_reg[USB3_PHY_SW_RESET]);
/* start PCS/Serdes to operation mode */
@ -556,6 +566,25 @@ static int msm_ssphy_qmp_dp_combo_reset(struct usb_phy *uphy)
phy);
int ret = 0;
if (phy->phy.flags & PHY_USB_DP_CONCURRENT_MODE) {
dev_dbg(uphy->dev, "Resetting USB part of QMP phy\n");
/* Assert USB3 PHY CSR reset */
ret = reset_control_assert(phy->phy_reset);
if (ret) {
dev_err(uphy->dev, "phy_reset assert failed\n");
goto exit;
}
/* Deassert USB3 PHY CSR reset */
ret = reset_control_deassert(phy->phy_reset);
if (ret) {
dev_err(uphy->dev, "phy_reset deassert failed\n");
goto exit;
}
return 0;
}
dev_dbg(uphy->dev, "Global reset of QMP DP combo phy\n");
/* Assert global PHY reset */
ret = reset_control_assert(phy->global_phy_reset);

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
*/
#ifndef __LINUX_USB_DWC3_MSM_H
@ -19,6 +19,7 @@
#define EUD_SPOOF_DISCONNECT BIT(6)
#define EUD_SPOOF_CONNECT BIT(7)
#define PHY_SUS_OVERRIDE BIT(8)
#define PHY_USB_DP_CONCURRENT_MODE BIT(9)
/*
* The following are bit fields describing the USB BAM options.
@ -135,7 +136,7 @@ int msm_data_fifo_config(struct usb_ep *ep, unsigned long addr, u32 size,
u8 dst_pipe_idx);
bool msm_dwc3_reset_ep_after_lpm(struct usb_gadget *gadget);
int msm_dwc3_reset_dbm_ep(struct usb_ep *ep);
int dwc3_msm_release_ss_lane(struct device *dev);
int dwc3_msm_release_ss_lane(struct device *dev, bool usb_dp_concurrent_mode);
bool usb_get_remote_wakeup_status(struct usb_gadget *gadget);
#else
static inline struct usb_ep *usb_ep_autoconfig_by_name(
@ -162,7 +163,7 @@ static inline bool msm_dwc3_reset_ep_after_lpm(struct usb_gadget *gadget)
{ return false; }
static inline int msm_dwc3_reset_dbm_ep(struct usb_ep *ep)
{ return -ENODEV; }
static inline int dwc3_msm_release_ss_lane(struct device *dev)
static inline int dwc3_msm_release_ss_lane(struct device *dev, bool usb_dp_concurrent_mode)
{ return -ENODEV; }
static bool __maybe_unused usb_get_remote_wakeup_status(struct usb_gadget *gadget)
{ return false; }