diff --git a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt index 51376cbe5f3d..a5c5db6a0b2d 100644 --- a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt +++ b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt @@ -100,6 +100,15 @@ i.mx specific properties It's recommended to specify the over current polarity. - power-active-high: power signal polarity is active high - external-vbus-divider: enables off-chip resistor divider for Vbus +- samsung,picophy-pre-emp-curr-control: HS Transmitter Pre-Emphasis Current + Control. This signal controls the amount of current sourced to the + USB_OTG*_DP and USB_OTG*_DN pins after a J-to-K or K-to-J transition. + The range is from 0x0 to 0x3, the default value is 0x1. + Details can refer to TXPREEMPAMPTUNE0 bits of USBNC_n_PHY_CFG1. +- samsung,picophy-dc-vol-level-adjust: HS DC Voltage Level Adjustment. + Adjust the high-speed transmitter DC level voltage. + The range is from 0x0 to 0xf, the default value is 0x3. + Details can refer to TXVREFTUNE0 bits of USBNC_n_PHY_CFG1. Example: diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c index c39e2b615ac6..25c65accf089 100644 --- a/drivers/usb/chipidea/ci_hdrc_imx.c +++ b/drivers/usb/chipidea/ci_hdrc_imx.c @@ -165,6 +165,11 @@ static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev) if (of_usb_get_phy_mode(np) == USBPHY_INTERFACE_MODE_ULPI) data->ulpi = 1; + of_property_read_u32(np, "samsung,picophy-pre-emp-curr-control", + &data->emp_curr_control); + of_property_read_u32(np, "samsung,picophy-dc-vol-level-adjust", + &data->dc_vol_level_adjust); + return data; } @@ -609,7 +614,12 @@ static int __maybe_unused ci_hdrc_imx_suspend(struct device *dev) } } - return imx_controller_suspend(dev); + ret = imx_controller_suspend(dev); + if (ret) + return ret; + + pinctrl_pm_select_sleep_state(dev); + return ret; } static int __maybe_unused ci_hdrc_imx_resume(struct device *dev) @@ -617,6 +627,7 @@ static int __maybe_unused ci_hdrc_imx_resume(struct device *dev) struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); int ret; + pinctrl_pm_select_default_state(dev); ret = imx_controller_resume(dev); if (!ret && data->supports_runtime_pm) { pm_runtime_disable(dev); diff --git a/drivers/usb/chipidea/ci_hdrc_imx.h b/drivers/usb/chipidea/ci_hdrc_imx.h index 99f846119c00..999c65390b7f 100644 --- a/drivers/usb/chipidea/ci_hdrc_imx.h +++ b/drivers/usb/chipidea/ci_hdrc_imx.h @@ -26,6 +26,8 @@ struct imx_usbmisc_data { unsigned int ext_vbus:1; /* Vbus from exteranl event */ struct usb_phy *usb_phy; enum usb_dr_mode available_role; /* runtime usb dr mode */ + int emp_curr_control; + int dc_vol_level_adjust; }; int imx_usbmisc_init(struct imx_usbmisc_data *data); diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c index 322e4de6b24a..6d8331e7da99 100644 --- a/drivers/usb/chipidea/usbmisc_imx.c +++ b/drivers/usb/chipidea/usbmisc_imx.c @@ -128,6 +128,12 @@ #define MX7D_USB_OTG_PHY_STATUS_VBUS_VLD BIT(3) #define MX7D_USB_OTG_PHY_STATUS_CHRGDET BIT(29) +#define MX7D_USB_OTG_PHY_CFG1 0x30 +#define TXPREEMPAMPTUNE0_BIT 28 +#define TXPREEMPAMPTUNE0_MASK (3 << 28) +#define TXVREFTUNE0_BIT 20 +#define TXVREFTUNE0_MASK (0xf << 20) + #define MX6_USB_OTG_WAKEUP_BITS (MX6_BM_WAKEUP_ENABLE | MX6_BM_VBUS_WAKEUP | \ MX6_BM_ID_WAKEUP) @@ -649,6 +655,21 @@ static int usbmisc_imx7d_init(struct imx_usbmisc_data *data) writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID | MX7D_USBNC_AUTO_RESUME, usbmisc->base + MX7D_USBNC_USB_CTRL2); + /* PHY tuning for signal quality */ + reg = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG1); + if (data->emp_curr_control && data->emp_curr_control <= + (TXPREEMPAMPTUNE0_MASK >> TXPREEMPAMPTUNE0_BIT)) { + reg &= ~TXPREEMPAMPTUNE0_MASK; + reg |= (data->emp_curr_control << TXPREEMPAMPTUNE0_BIT); + } + + if (data->dc_vol_level_adjust && data->dc_vol_level_adjust <= + (TXVREFTUNE0_MASK >> TXVREFTUNE0_BIT)) { + reg &= ~TXVREFTUNE0_MASK; + reg |= (data->dc_vol_level_adjust << TXVREFTUNE0_BIT); + } + + writel(reg, usbmisc->base + MX7D_USB_OTG_PHY_CFG1); } spin_unlock_irqrestore(&usbmisc->lock, flags);