From 85ca34183b3b49e4cef87524bd9913d389efc915 Mon Sep 17 00:00:00 2001 From: Mayank Rana Date: Mon, 2 May 2022 15:50:18 -0700 Subject: [PATCH 1/2] usb: dwc3: SW WA for USB CV9(TD 9.23) compliance test failure eUSB2 repeater is unable to block KJKJ pulse during ESE1. This is resulting into eUSB2 PHY and repeater going out of sync and next link up in high speed fails. Fix this issue by performing soft reset of eUSB2 PHY. Change-Id: I9913fe4cab03b344dea0525f7a72282cd743a915 Signed-off-by: Mayank Rana --- drivers/usb/dwc3/dwc3-msm-core.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/usb/dwc3/dwc3-msm-core.c b/drivers/usb/dwc3/dwc3-msm-core.c index 86bf95ec3aba..5c179a9110f3 100644 --- a/drivers/usb/dwc3/dwc3-msm-core.c +++ b/drivers/usb/dwc3/dwc3-msm-core.c @@ -3204,6 +3204,19 @@ static void dwc3_msm_update_imem_pid(struct dwc3 *dwc) } } +static void mdwc3_usb2_phy_soft_reset(struct dwc3_msm *mdwc) +{ + u32 val; + + val = dwc3_msm_read_reg(mdwc->base, DWC3_GUSB2PHYCFG(0)); + dwc3_msm_write_reg(mdwc->base, DWC3_GUSB2PHYCFG(0), + val | DWC3_GUSB2PHYCFG_PHYSOFTRST); + udelay(20); + val = dwc3_msm_read_reg(mdwc->base, DWC3_GUSB2PHYCFG(0)); + val &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; + dwc3_msm_write_reg(mdwc->base, DWC3_GUSB2PHYCFG(0), val); +} + void dwc3_msm_notify_event(struct dwc3 *dwc, enum dwc3_notify_event event, unsigned int value) { @@ -3234,6 +3247,20 @@ void dwc3_msm_notify_event(struct dwc3 *dwc, break; case DWC3_CONTROLLER_CONNDONE_EVENT: dev_dbg(mdwc->dev, "DWC3_CONTROLLER_CONNDONE_EVENT received\n"); + + /* + * SW WA for CV9 RESET DEVICE TEST(TD 9.23) compliance failure. + * Visit eUSB2 phy driver for more details. + */ + WARN_ON(mdwc->hs_phy->flags & PHY_HOST_MODE); + if (mdwc->use_eusb2_phy && + (dwc->gadget->speed >= USB_SPEED_SUPER)) { + usb_phy_notify_connect(mdwc->hs_phy, dwc->gadget->speed); + udelay(20); + /* Perform usb2 phy soft reset as given workaround */ + mdwc3_usb2_phy_soft_reset(mdwc); + } + /* * Add power event if the dbm indicates coming out of L1 by * interrupt From 4977a05f93dedd07a0af8efee4e3e5ab5789aa86 Mon Sep 17 00:00:00 2001 From: Mayank Rana Date: Mon, 2 May 2022 16:36:57 -0700 Subject: [PATCH 2/2] usb: dwc3: Enable u1u2 functionality with USB Gen1 speed Enable u1u2 functionality in USB device mode when USB is operating in super speed (gen1 speed). Change-Id: I14056274b68c3ed395ee3673312606ded68afcd6 Signed-off-by: Mayank Rana --- drivers/usb/dwc3/dwc3-msm-core.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/usb/dwc3/dwc3-msm-core.c b/drivers/usb/dwc3/dwc3-msm-core.c index 5c179a9110f3..a3a01127a007 100644 --- a/drivers/usb/dwc3/dwc3-msm-core.c +++ b/drivers/usb/dwc3/dwc3-msm-core.c @@ -587,6 +587,8 @@ struct dwc3_msm { bool dis_sending_cm_l1_quirk; bool use_eusb2_phy; bool force_gen1; + bool cached_dis_u1_entry_quirk; + bool cached_dis_u2_entry_quirk; }; #define USB_HSPHY_3P3_VOL_MIN 3050000 /* uV */ @@ -3217,6 +3219,34 @@ static void mdwc3_usb2_phy_soft_reset(struct dwc3_msm *mdwc) dwc3_msm_write_reg(mdwc->base, DWC3_GUSB2PHYCFG(0), val); } +static void mdwc3_update_u1u2_value(struct dwc3 *dwc) +{ + struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent); + static bool read_u1u2; + + /* cache DT based initial value once */ + if (!read_u1u2) { + mdwc->cached_dis_u1_entry_quirk = dwc->dis_u1_entry_quirk; + mdwc->cached_dis_u2_entry_quirk = dwc->dis_u2_entry_quirk; + read_u1u2 = true; + dbg_log_string("cached_dt_param: u1_disable:%d u2_disable:%d\n", + mdwc->cached_dis_u1_entry_quirk, mdwc->cached_dis_u2_entry_quirk); + } + + /* Enable u1u2 for USB super speed (gen1) only with quirks enable it */ + if (dwc->speed == DWC3_DSTS_SUPERSPEED) { + dwc->dis_u1_entry_quirk = mdwc->cached_dis_u1_entry_quirk; + dwc->dis_u2_entry_quirk = mdwc->cached_dis_u2_entry_quirk; + } else { + dwc->dis_u1_entry_quirk = true; + dwc->dis_u2_entry_quirk = true; + } + + dbg_log_string("speed:%d u1:%s u2:%s\n", + dwc->speed, dwc->dis_u1_entry_quirk ? "disabled" : "enabled", + dwc->dis_u2_entry_quirk ? "disabled" : "enabled"); +} + void dwc3_msm_notify_event(struct dwc3 *dwc, enum dwc3_notify_event event, unsigned int value) { @@ -3271,6 +3301,7 @@ void dwc3_msm_notify_event(struct dwc3 *dwc, PWR_EVNT_LPM_OUT_L1_MASK, 1); atomic_set(&mdwc->in_lpm, 0); + mdwc3_update_u1u2_value(dwc); break; case DWC3_GSI_EVT_BUF_ALLOC: dev_dbg(mdwc->dev, "DWC3_GSI_EVT_BUF_ALLOC\n");