]> rtime.felk.cvut.cz Git - hercules2020/nv-tegra/linux-4.4.git/commitdiff
uphy: xhci: tegra: t210: enable vbus after HCRST
authorBH Hsieh <bhsieh@nvidia.com>
Fri, 24 Mar 2017 06:41:55 +0000 (14:41 +0800)
committermobile promotions <svcmobile_promotions@nvidia.com>
Thu, 13 Apr 2017 07:47:18 +0000 (00:47 -0700)
Realtek R8152 is observed violating spec and failed
to turn on termination after exiting Polling.Active
due to 12 ms timeout.

To avoid this issue, enable VBUS after HCRST instead
of before loading xusb firmware hence no reset SSPI
would interrupt Polling.RxEQ/Polling.Active state.

bug 200272921

Change-Id: I555acda4fd238d0b89b94d8a823c2150629361ec
Signed-off-by: BH Hsieh <bhsieh@nvidia.com>
Reviewed-on: http://git-master/r/1313776
(cherry picked from commit f48e0a8f2426932b653d0ffd337a6571050736f4)
Reviewed-on: http://git-master/r/1453256
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: svccoveritychecker <svccoveritychecker@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Shreshtha Sahu <ssahu@nvidia.com>
Tested-by: Shreshtha Sahu <ssahu@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
drivers/pinctrl/pinctrl-tegra21x-padctl-uphy.c
drivers/usb/host/xhci-tegra.c
include/soc/tegra/xusb.h

index a7034e028bf73e0a4c1949eccb26fe4ae624cecc..fabe23534c821a3f6463b435cf7ab88ab7c289bc 100644 (file)
@@ -2865,7 +2865,7 @@ static inline void tegra21x_hsic_trk(struct tegra_padctl_uphy *uphy, bool on)
 #define tegra21x_hsic_trk_on(uphy) tegra21x_hsic_trk(uphy, true)
 #define tegra21x_hsic_trk_off(uphy) tegra21x_hsic_trk(uphy, false)
 
-static int tegra21x_utmi_phy_init(struct phy *phy)
+int tegra21x_utmi_vbus_enable(struct phy *phy)
 {
        struct tegra_padctl_uphy *uphy = phy_get_drvdata(phy);
        int port = utmi_phy_to_port(phy);
@@ -2874,7 +2874,7 @@ static int tegra21x_utmi_phy_init(struct phy *phy)
        if (port < 0)
                return port;
 
-       TRACE(uphy->dev, "phy init UTMI port %d\n",  port);
+       TRACE(uphy->dev, "enable vbus-%d\n", port);
 
        mutex_lock(&uphy->lock);
 
@@ -2892,6 +2892,20 @@ static int tegra21x_utmi_phy_init(struct phy *phy)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(tegra21x_utmi_vbus_enable);
+
+static int tegra21x_utmi_phy_init(struct phy *phy)
+{
+       struct tegra_padctl_uphy *uphy = phy_get_drvdata(phy);
+       int port = utmi_phy_to_port(phy);
+
+       if (port < 0)
+               return port;
+
+       TRACE(uphy->dev, "phy init UTMI port %d\n", port);
+
+       return 0;
+}
 
 static int tegra21x_utmi_phy_exit(struct phy *phy)
 {
index 8deb0f59ed573a9d71ce1559d6b1fd518b43a74f..7190c14c1edd0594a35329785d700a1bb63024ab 100644 (file)
@@ -338,6 +338,7 @@ struct tegra_xhci_soc_config {
        void (*set_protection_level)(struct phy *utmi_phy,
                int level, enum tegra_vbus_dir dir);
        int (*utmi_vbus_power_on)(struct phy *phy);
+       int (*utmi_vbus_enable)(struct phy *phy);
        int (*utmi_vbus_power_off)(struct phy *phy);
        int (*overcurrent_detected)(struct phy *phy);
        void (*handle_overcurrent)(struct phy *phy);
@@ -1353,6 +1354,7 @@ static const struct tegra_xhci_soc_config tegra186_soc_config = {
                tegra18x_phy_xusb_utmi_pad_set_protection_level,
        .utmi_vbus_power_on = tegra18x_phy_xusb_utmi_vbus_power_on,
        .utmi_vbus_power_off = tegra18x_phy_xusb_utmi_vbus_power_off,
+       .utmi_vbus_enable = tegra18x_utmi_vbus_enable,
        .overcurrent_detected = tegra18x_phy_xusb_overcurrent_detected,
        .handle_overcurrent = tegra18x_phy_xusb_handle_overcurrent,
        .set_id_override = tegra18x_phy_xusb_set_id_override,
@@ -1391,6 +1393,7 @@ static const struct tegra_xhci_soc_config tegra210b01_soc_config = {
                tegra21x_phy_xusb_utmi_pad_set_protection_level,
        .utmi_vbus_power_on = tegra21x_phy_xusb_utmi_vbus_power_on,
        .utmi_vbus_power_off = tegra21x_phy_xusb_utmi_vbus_power_off,
+       .utmi_vbus_enable = tegra21x_utmi_vbus_enable,
        .overcurrent_detected = tegra21x_phy_xusb_overcurrent_detected,
        .handle_overcurrent = tegra21x_phy_xusb_handle_overcurrent,
        .set_id_override = tegra21x_phy_xusb_set_id_override,
@@ -1430,6 +1433,7 @@ static const struct tegra_xhci_soc_config tegra210_soc_config = {
                tegra21x_phy_xusb_utmi_pad_set_protection_level,
        .utmi_vbus_power_on = tegra21x_phy_xusb_utmi_vbus_power_on,
        .utmi_vbus_power_off = tegra21x_phy_xusb_utmi_vbus_power_off,
+       .utmi_vbus_enable = tegra21x_utmi_vbus_enable,
        .overcurrent_detected = tegra21x_phy_xusb_overcurrent_detected,
        .handle_overcurrent = tegra21x_phy_xusb_handle_overcurrent,
        .set_id_override = tegra21x_phy_xusb_set_id_override,
@@ -1877,6 +1881,18 @@ static void tegra_xhci_probe_finish(const struct firmware *fw, void *context)
                goto put_usb2_hcd;
        device_wakeup_enable(tegra->hcd->self.controller);
 
+       if (tegra->soc_config->utmi_vbus_enable) {
+               for (i = 0; i < tegra->soc_config->num_phys[UTMI_PHY]; i++) {
+                       if (tegra->phys[UTMI_PHY][i]) {
+                               ret = tegra->soc_config->utmi_vbus_enable(
+                                       tegra->phys[UTMI_PHY][i]);
+                               if (ret)
+                                       dev_err(dev, "enable port vbus-%d failed %d\n",
+                                               i, ret);
+                       }
+               }
+       }
+
        xhci = hcd_to_xhci(tegra->hcd);
        xhci->shared_hcd = usb_create_shared_hcd(&tegra_xhci_hc_driver,
                                                 dev, dev_name(dev),
index 099d266b14db49437fce3392c64795d274d79f2b..9e332bbded67e1cfd0afdc45f4357f9ccbbf158c 100644 (file)
@@ -107,6 +107,7 @@ void tegra21x_phy_xusb_utmi_pad_set_protection_level(struct phy *phy, int level,
 u32 tegra21x_phy_xusb_noncompliant_div_detect(struct phy *phy);
 int tegra21x_phy_xusb_utmi_vbus_power_on(struct phy *phy);
 int tegra21x_phy_xusb_utmi_vbus_power_off(struct phy *phy);
+int tegra21x_utmi_vbus_enable(struct phy *phy);
 int tegra21x_phy_xusb_overcurrent_detected(struct phy *phy);
 void tegra21x_phy_xusb_handle_overcurrent(struct phy *phy);
 int tegra21x_phy_xusb_set_id_override(struct phy *phy);
@@ -220,6 +221,11 @@ static inline int tegra21x_phy_xusb_utmi_vbus_power_off(struct phy *phy)
        return 0;
 }
 
+static inline int tegra21x_utmi_vbus_enable(struct phy *phy)
+{
+       return 0;
+}
+
 static inline int tegra21x_phy_xusb_overcurrent_detected(struct phy *phy)
 {
        return 0;
@@ -351,6 +357,7 @@ bool tegra18x_phy_xusb_utmi_pad_primary_charger_detect(struct phy *phy);
 bool tegra18x_phy_xusb_utmi_pad_secondary_charger_detect(struct phy *phy);
 int tegra18x_phy_xusb_utmi_vbus_power_on(struct phy *phy);
 int tegra18x_phy_xusb_utmi_vbus_power_off(struct phy *phy);
+int tegra18x_utmi_vbus_enable(struct phy *phy);
 int tegra18x_phy_xusb_overcurrent_detected(struct phy *phy);
 void tegra18x_phy_xusb_handle_overcurrent(struct phy *phy);
 int tegra18x_phy_xusb_set_id_override(struct phy *phy);
@@ -464,6 +471,11 @@ static inline int tegra18x_phy_xusb_utmi_vbus_power_off(struct phy *phy)
        return 0;
 }
 
+static inline int tegra18x_utmi_vbus_enable(struct phy *phy)
+{
+       return 0;
+}
+
 static inline int tegra18x_phy_xusb_overcurrent_detected(struct phy *phy)
 {
        return 0;