Added new bitfield GRSTCTL_CLOCK_SWITH_TIMER in GRSTCTL register. This bitfield applicable HSOTG cores v5.00 or higher and not applicable to HS/FS IOT devices. This bitfield must be programmed to 3'b010 if core will be used in Low-speed and core configured for any HS/FS PHY interface. This bitfield must be programmed to 3'b111 if core configured to use either: - HS PHY interface UTMI or ULPI - FS PHY any interface Signed-off-by: Minas Harutyunyan <Minas.Harutyunyan@xxxxxxxxxxxx> --- drivers/usb/dwc2/core.c | 37 +++++++++++++++++++++++++++++++++++++ drivers/usb/dwc2/hw.h | 11 +++++++++++ 2 files changed, 48 insertions(+) diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index b7a76eb089c9..9919ab725d54 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -980,6 +980,41 @@ void dwc2_init_fs_ls_pclk_sel(struct dwc2_hsotg *hsotg) dwc2_writel(hsotg, hcfg, HCFG); } +static void dwc2_set_clock_switch_timer(struct dwc2_hsotg *hsotg) +{ + u32 grstctl, gsnpsid, val = 0; + + gsnpsid = dwc2_readl(hsotg, GSNPSID); + + /* + * Applicable only to HSOTG core v5.00a or higher. + * Not applicable to HS/FS IOT devices. + */ + if ((gsnpsid & ~DWC2_CORE_REV_MASK) != DWC2_OTG_ID || + gsnpsid < DWC2_CORE_REV_5_00a) + return; + + if ((hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI && + hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_NOT_SUPPORTED) || + (hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI && + hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_NOT_SUPPORTED) || + (hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_NOT_SUPPORTED && + hsotg->hw_params.fs_phy_type != GHWCFG2_FS_PHY_TYPE_NOT_SUPPORTED)) { + val = GRSTCTL_CLOCK_SWITH_TIMER_VALUE_DIS; + } + + if (hsotg->params.speed == DWC2_SPEED_PARAM_LOW && + hsotg->hw_params.hs_phy_type != GHWCFG2_HS_PHY_TYPE_NOT_SUPPORTED && + hsotg->hw_params.fs_phy_type != GHWCFG2_FS_PHY_TYPE_NOT_SUPPORTED) { + val = GRSTCTL_CLOCK_SWITH_TIMER_VALUE_147; + } + + grstctl = dwc2_readl(hsotg, GRSTCTL); + grstctl &= ~GRSTCTL_CLOCK_SWITH_TIMER_MASK; + grstctl |= GRSTCTL_CLOCK_SWITH_TIMER(val); + dwc2_writel(hsotg, grstctl, GRSTCTL); +} + static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) { u32 usbcfg, ggpio, i2cctl; @@ -997,6 +1032,8 @@ static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) usbcfg |= GUSBCFG_PHYSEL; dwc2_writel(hsotg, usbcfg, GUSBCFG); + dwc2_set_clock_switch_timer(hsotg); + /* Reset after a PHY select */ retval = dwc2_core_reset(hsotg, false); diff --git a/drivers/usb/dwc2/hw.h b/drivers/usb/dwc2/hw.h index 5e449393b0d7..48699caa8739 100644 --- a/drivers/usb/dwc2/hw.h +++ b/drivers/usb/dwc2/hw.h @@ -99,6 +99,17 @@ #define GRSTCTL_AHBIDLE BIT(31) #define GRSTCTL_DMAREQ BIT(30) #define GRSTCTL_CSFTRST_DONE BIT(29) +#define GRSTCTL_CLOCK_SWITH_TIMER_MASK (0x7 << 11) +#define GRSTCTL_CLOCK_SWITH_TIMER_SHIFT 11 +#define GRSTCTL_CLOCK_SWITH_TIMER_VALUE_19 0x0 +#define GRSTCTL_CLOCK_SWITH_TIMER_VALUE_15 0x1 +#define GRSTCTL_CLOCK_SWITH_TIMER_VALUE_147 0x2 +#define GRSTCTL_CLOCK_SWITH_TIMER_VALUE_50 0x3 +#define GRSTCTL_CLOCK_SWITH_TIMER_VALUE_100 0x4 +#define GRSTCTL_CLOCK_SWITH_TIMER_VALUE_125 0x5 +#define GRSTCTL_CLOCK_SWITH_TIMER_VALUE_200 0x6 +#define GRSTCTL_CLOCK_SWITH_TIMER_VALUE_DIS 0x7 +#define GRSTCTL_CLOCK_SWITH_TIMER(_x) ((_x) << 11) #define GRSTCTL_TXFNUM_MASK (0x1f << 6) #define GRSTCTL_TXFNUM_SHIFT 6 #define GRSTCTL_TXFNUM_LIMIT 0x1f -- 2.41.0