diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index 0c10bd0c32fd..16d6ac97f23b 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -288,6 +288,11 @@ enum dwc2_ep0_state { * core has been configured to work at either data path * width. * 8 or 16 (default 16 if available) + * @eusb2_disc: Specifies whether eUSB2 PHY disconnect support flow + * applicable or no. Applicable in device mode of HSOTG + * and HS IOT cores v5.00 or higher. + * 0 - eUSB2 PHY disconnect support flow not applicable + * 1 - eUSB2 PHY disconnect support flow applicable * @phy_ulpi_ddr: Specifies whether the ULPI operates at double or single * data rate. This parameter is only applicable if phy_type * is ULPI. @@ -442,6 +447,7 @@ struct dwc2_core_params { #define DWC2_SPEED_PARAM_LOW 2 u8 phy_utmi_width; + bool eusb2_disc; bool phy_ulpi_ddr; bool phy_ulpi_ext_vbus; bool enable_dynamic_fifo; diff --git a/drivers/usb/dwc2/debugfs.c b/drivers/usb/dwc2/debugfs.c index 1d72ece9cfe4..7c82ab590401 100644 --- a/drivers/usb/dwc2/debugfs.c +++ b/drivers/usb/dwc2/debugfs.c @@ -686,6 +686,7 @@ static int params_show(struct seq_file *seq, void *v) print_param(seq, p, host_channels); print_param(seq, p, phy_type); print_param(seq, p, phy_utmi_width); + print_param(seq, p, eusb2_disc); print_param(seq, p, phy_ulpi_ddr); print_param(seq, p, phy_ulpi_ext_vbus); print_param(seq, p, i2c_enable); diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c index eb677c3cfd0b..c47524483f48 100644 --- a/drivers/usb/dwc2/params.c +++ b/drivers/usb/dwc2/params.c @@ -475,6 +475,7 @@ static void dwc2_set_default_params(struct dwc2_hsotg *hsotg) dwc2_set_param_lpm(hsotg); p->phy_ulpi_ddr = false; p->phy_ulpi_ext_vbus = false; + p->eusb2_disc = false; p->enable_dynamic_fifo = hw->enable_dynamic_fifo; p->en_multiple_tx_fifo = hw->en_multiple_tx_fifo; @@ -737,6 +738,25 @@ static void dwc2_check_param_tx_fifo_sizes(struct dwc2_hsotg *hsotg) } } +static void dwc2_check_param_eusb2_disc(struct dwc2_hsotg *hsotg) +{ + u32 gsnpsid; + + if (!hsotg->params.eusb2_disc) + return; + gsnpsid = dwc2_readl(hsotg, GSNPSID); + /* + * eusb2_disc not supported by FS IOT devices. + * For other cores, it supported starting from version 5.00a + */ + if ((gsnpsid & ~DWC2_CORE_REV_MASK) == DWC2_FS_IOT_ID || + (gsnpsid & DWC2_CORE_REV_MASK) < + (DWC2_CORE_REV_5_00a & DWC2_CORE_REV_MASK)) { + hsotg->params.eusb2_disc = false; + return; + } +} + #define CHECK_RANGE(_param, _min, _max, _def) do { \ if ((int)(hsotg->params._param) < (_min) || \ (hsotg->params._param) > (_max)) { \ @@ -765,6 +785,8 @@ static void dwc2_check_params(struct dwc2_hsotg *hsotg) dwc2_check_param_speed(hsotg); dwc2_check_param_phy_utmi_width(hsotg); dwc2_check_param_power_down(hsotg); + dwc2_check_param_eusb2_disc(hsotg); + CHECK_BOOL(enable_dynamic_fifo, hw->enable_dynamic_fifo); CHECK_BOOL(en_multiple_tx_fifo, hw->en_multiple_tx_fifo); CHECK_BOOL(i2c_enable, hw->i2c_enable);