From be62fb03e60d1e5066a0546fc1089a261a29cd2d Mon Sep 17 00:00:00 2001 From: Wesley Cheng Date: Tue, 4 Apr 2023 15:56:21 -0700 Subject: [PATCH 1/2] usb: repeater: Add repeater API for fetching HW revision Introduce a callback in the repeater driver for getting the repeater revision being used on the platform. Some repeater versions may require different workaround/fixes for certain issues. Change-Id: I7819d1fa5fe4cee92389388c5c6f1986e6250e9e Signed-off-by: Wesley Cheng --- drivers/usb/repeater/repeater-qti-pmic-eusb2.c | 15 +++++++++++++++ include/linux/usb/repeater.h | 11 ++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) 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 */ From 61e83e608b99f673d0aa93b154cd56b84d8af211 Mon Sep 17 00:00:00 2001 From: Wesley Cheng Date: Tue, 4 Apr 2023 16:00:28 -0700 Subject: [PATCH 2/2] usb: dwc3: dwc3-msm-core: Apply PHY soft reset for TD 9.23 WA for Kohala V1 The Kohala V1 USB repeater requires a PHY soft reset from the controller register as part of the workaround for the TD 9.23 failure. Platforms using V2 onwards (or non PMIC based repeaters) do not require this portion of the workaround in place. Change-Id: I266fbe4c7bddd372486440260bfd1ed58de59238 Signed-off-by: Wesley Cheng --- drivers/usb/dwc3/dwc3-msm-core.c | 36 +++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) 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); + } } /*