]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
pcie: host: tegra: optimize PCIe linkup check
authorVidya Sagar <vidyas@nvidia.com>
Mon, 25 Jan 2016 10:42:44 +0000 (16:12 +0530)
committermobile promotions <svcmobile_promotions@nvidia.com>
Tue, 2 Feb 2016 16:42:44 +0000 (08:42 -0800)
optimizes pcie link up checking process by initially waiting
for 20ms for UPHY lane's TX_RDET_STATUS to get set if there is any
end point connected, thereby avoiding any further waiting for linkup
on root ports

Bug 200165778
Bug 200163241

Change-Id: I2805af37e2fdf4d16f0233dbb7a44b2f8d3565b3
Signed-off-by: Vidya Sagar <vidyas@nvidia.com>
Reviewed-on: http://git-master/r/936894
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
arch/arm/mach-tegra/include/mach/tegra_usb_pad_ctrl.h
drivers/pci/host/pci-tegra.c
drivers/platform/tegra/tegra_usb_pad_ctrl.c

index 1df0808994ce63364af2c706f3332b13b33c8e2a..0fc8a00278d81a42041937e670438483c01ad32c 100644 (file)
@@ -147,8 +147,13 @@ static inline enum padctl_lane usb3_laneowner_to_lane_enum(u8 laneowner)
 #define XUSB_PADCTL_UPHY_MISC_PAD_P1_CTL1_AUX_TX_RDET_STATUS   (1 << 7)
 
 #define XUSB_PADCTL_UPHY_MISC_PAD_P2_CTL1      0x4E0
+#define XUSB_PADCTL_UPHY_MISC_PAD_P2_CTL1_AUX_TX_RDET_STATUS   (1 << 7)
+
 #define XUSB_PADCTL_UPHY_MISC_PAD_P3_CTL1      0x520
+#define XUSB_PADCTL_UPHY_MISC_PAD_P3_CTL1_AUX_TX_RDET_STATUS   (1 << 7)
+
 #define XUSB_PADCTL_UPHY_MISC_PAD_P4_CTL1      0x560
+#define XUSB_PADCTL_UPHY_MISC_PAD_P4_CTL1_AUX_TX_RDET_STATUS   (1 << 7)
 
 #define XUSB_PADCTL_UPHY_MISC_PAD_P0_CTL2      0x464
 #define XUSB_PADCTL_UPHY_MISC_PAD_P0_CTL2_TX_IDDQ      (1 << 0)
index 82ef153a3546572cc7382619834e5dd90cf5f717..385c9ddf8bee9476d65704c5625b8aaa8d8b618c 100644 (file)
@@ -365,7 +365,7 @@ static struct of_device_id tegra_pcie_pd[] = {
 #endif
 
 #if defined(CONFIG_ARCH_TEGRA_21x_SOC)
-static u32 rp_to_lane_map[] = {1, 0};
+static u32 rp_to_lane_map[2][4] = { {1, 2, 3, 4}, {0} };
 #endif
 
 struct tegra_pcie_soc_data {
@@ -1753,6 +1753,17 @@ static void tegra_pcie_port_disable(struct tegra_pcie_port *port)
        afi_writel(port->pcie, data, AFI_PCIE_CONFIG);
 }
 
+#if defined(CONFIG_ARCH_TEGRA_21x_SOC)
+static bool get_rdet_status(u32 index)
+{
+       u32 i = 0;
+       bool flag = 0;
+       for (i = 0; i < ARRAY_SIZE(rp_to_lane_map[index]); i++)
+               flag |= tegra_phy_get_lane_rdet(rp_to_lane_map[index][i]);
+       return flag;
+}
+#endif
+
 /*
  * FIXME: If there are no PCIe cards attached, then calling this function
  * can result in the increase of the bootup time as there are big timeout
@@ -1765,6 +1776,10 @@ static bool tegra_pcie_port_check_link(struct tegra_pcie_port *port)
        unsigned long value;
 
        PR_FUNC_LINE;
+#if defined(CONFIG_ARCH_TEGRA_21x_SOC)
+       if (!get_rdet_status(port->index))
+               return false;
+#endif
        do {
                unsigned int timeout = TEGRA_PCIE_LINKUP_TIMEOUT;
 
@@ -1774,15 +1789,6 @@ static bool tegra_pcie_port_check_link(struct tegra_pcie_port *port)
                                return true;
                        usleep_range(1000, 2000);
                } while (--timeout);
-#if defined(CONFIG_ARCH_TEGRA_21x_SOC)
-               if (tegra_phy_get_lane_rdet(
-                               rp_to_lane_map[port->index]))
-                       goto retry;
-               else
-                       return false;
-
-retry:
-#endif
                dev_info(port->pcie->dev, "link %u down, retrying\n",
                                        port->index);
                tegra_pcie_port_reset(port);
@@ -2074,7 +2080,12 @@ static void tegra_pcie_check_ports(struct tegra_pcie *pcie)
        /* Wait for clock to latch (min of 100us) */
        udelay(100);
        tegra_periph_reset_deassert(pcie->pcie_xclk);
-
+       /* at this point in time, there is no end point which would
+        * take more than 20 msec for root port to detect receiver and
+        * set AUX_TX_RDET_STATUS bit. This would bring link up checking
+        * time from its current value (around 200ms) to flat 20ms
+        */
+       msleep(20);
        list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
                if (tegra_pcie_port_check_link(port)) {
                        port->status = 1;
index 18867228dcff9c49178f89475b55fd8a63dfa85a..c87b98b948f8693a5b18562ef6b9d2590f44b721 100644 (file)
@@ -2099,6 +2099,21 @@ bool tegra_phy_get_lane_rdet(u8 lane_num)
                data = data &
                        XUSB_PADCTL_UPHY_MISC_PAD_P1_CTL1_AUX_TX_RDET_STATUS;
                break;
+       case 2:
+               data = readl(pad_base + XUSB_PADCTL_UPHY_MISC_PAD_P2_CTL1);
+               data = data &
+                       XUSB_PADCTL_UPHY_MISC_PAD_P2_CTL1_AUX_TX_RDET_STATUS;
+               break;
+       case 3:
+               data = readl(pad_base + XUSB_PADCTL_UPHY_MISC_PAD_P3_CTL1);
+               data = data &
+                       XUSB_PADCTL_UPHY_MISC_PAD_P3_CTL1_AUX_TX_RDET_STATUS;
+               break;
+       case 4:
+               data = readl(pad_base + XUSB_PADCTL_UPHY_MISC_PAD_P4_CTL1);
+               data = data &
+                       XUSB_PADCTL_UPHY_MISC_PAD_P4_CTL1_AUX_TX_RDET_STATUS;
+               break;
        default:
                return 0;
        }