diff --git a/drivers/usb/dwc3/dwc3-msm-core.c b/drivers/usb/dwc3/dwc3-msm-core.c index 1027c6f166a8..b02e53d5557c 100644 --- a/drivers/usb/dwc3/dwc3-msm-core.c +++ b/drivers/usb/dwc3/dwc3-msm-core.c @@ -47,6 +47,7 @@ #include #include #include +#include #include "core.h" #include "gadget.h" @@ -213,6 +214,9 @@ #define DWC3_DEPCFG_RETRY BIT(15) #define DWC3_DEPCFG_TRB_WB BIT(14) +/* USB repeater */ +#define USB_REPEATER_V1 0x1 + enum dbm_reg { DBM_EP_CFG, DBM_DATA_FIFO, @@ -3259,6 +3263,21 @@ static void mdwc3_update_u1u2_value(struct dwc3 *dwc) dwc->dis_u2_entry_quirk ? "disabled" : "enabled"); } +int dwc3_msm_get_repeater_ver(struct dwc3_msm *mdwc) +{ + struct usb_repeater *ur = NULL; + int ver; + + ur = devm_usb_get_repeater_by_phandle(mdwc->hs_phy->dev, "usb-repeater", 0); + if (IS_ERR(ur)) + return -ENODEV; + + ver = usb_repeater_get_version(ur); + usb_put_repeater(ur); + + return ver; +} + void dwc3_msm_notify_event(struct dwc3 *dwc, enum dwc3_notify_event event, unsigned int value) { @@ -3298,9 +3317,20 @@ void dwc3_msm_notify_event(struct dwc3 *dwc, 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); + + /* + * Certain USB repeater HW revisions will have a fix on + * silicon. Limit the controller PHY soft reset to the + * version which requires it. + */ + if (dwc3_msm_get_repeater_ver(mdwc) == USB_REPEATER_V1) { + udelay(20); + /* + * Perform usb2 phy soft reset as given + * workaround + */ + mdwc3_usb2_phy_soft_reset(mdwc); + } } /* diff --git a/drivers/usb/repeater/repeater-qti-pmic-eusb2.c b/drivers/usb/repeater/repeater-qti-pmic-eusb2.c index a75a7c969442..b7f9721d7931 100644 --- a/drivers/usb/repeater/repeater-qti-pmic-eusb2.c +++ b/drivers/usb/repeater/repeater-qti-pmic-eusb2.c @@ -22,6 +22,9 @@ #define EUSB2_1P8_VOL_MAX 1800000 /* uV */ #define EUSB2_1P8_HPM_LOAD 32000 /* uA */ +/* Repeater REVID registers */ +#define EUSB2_REVISION1 0x00 + /* eUSB2 status registers */ #define EUSB2_RPTR_STATUS 0x08 #define RPTR_OK BIT(7) @@ -177,6 +180,17 @@ static void eusb2_repeater_update_seq(struct eusb2_repeater *er, } } +static int eusb2_repeater_get_version(struct usb_repeater *ur) +{ + struct eusb2_repeater *er = + container_of(ur, struct eusb2_repeater, ur); + u8 reg; + + eusb2_repeater_reg_read(er, ®, EUSB2_REVISION1, 1); + + return reg; +} + static void eusb2_repeater_create_debugfs(struct eusb2_repeater *er) { er->usb2_crossover = U8_MAX; @@ -513,6 +527,7 @@ static int eusb2_repeater_probe(struct platform_device *pdev) er->ur.reset = eusb2_repeater_reset; er->ur.powerup = eusb2_repeater_powerup; er->ur.powerdown = eusb2_repeater_powerdown; + er->ur.get_version = eusb2_repeater_get_version; ret = usb_add_repeater_dev(&er->ur); if (ret) diff --git a/include/linux/usb/repeater.h b/include/linux/usb/repeater.h index 4cd34022391a..20876e985de2 100644 --- a/include/linux/usb/repeater.h +++ b/include/linux/usb/repeater.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef __LINUX_USB_REPEATER_H #define __LINUX_USB_REPEATER_H @@ -20,6 +20,7 @@ struct usb_repeater { int (*suspend)(struct usb_repeater *r, int suspend); int (*powerup)(struct usb_repeater *r); int (*powerdown)(struct usb_repeater *r); + int (*get_version)(struct usb_repeater *r); }; #if IS_ENABLED(CONFIG_USB_REPEATER) @@ -89,4 +90,12 @@ static inline int usb_repeater_powerdown(struct usb_repeater *r) else return 0; } + +static inline int usb_repeater_get_version(struct usb_repeater *r) +{ + if (r && r->get_version != NULL) + return r->get_version(r); + else + return -EINVAL; +} #endif /* __LINUX_USB_REPEATER_H */