/*
- * Copyright (c) 2013-2015, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2013-2016, NVIDIA CORPORATION. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
#define XUSB_PADCTL_UPHY_MISC_PAD_P0_CTL1 0x460
#define XUSB_PADCTL_UPHY_MISC_PAD_P0_CTL1_AUX_RX_IDLE_TH_MASK (0x3 << 24)
#define XUSB_PADCTL_UPHY_MISC_PAD_P0_CTL1_AUX_RX_IDLE_TH (1 << 24)
+#define XUSB_PADCTL_UPHY_MISC_PAD_P0_CTL1_AUX_TX_RDET_STATUS (1 << 7)
#define XUSB_PADCTL_UPHY_MISC_PAD_P1_CTL1 0x4A0
+#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_P3_CTL1 0x520
#define XUSB_PADCTL_UPHY_MISC_PAD_P4_CTL1 0x560
#endif
int usb3_phy_pad_enable(u32 lane_owner);
int pcie_phy_pad_enable(bool enable, int lane_owner);
+bool tegra_phy_get_lane_rdet(u8 lane_num);
int utmi_phy_iddq_override(bool set);
void tegra_usb_pad_reg_update(u32 reg_offset, u32 mask, u32 val);
#include <linux/pm_runtime.h>
#include <linux/tegra-powergate.h>
#include <linux/tegra-soc.h>
-#include <linux/pci-tegra.h>
#include <linux/of_device.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/of_pci.h>
+#include <linux/tegra_prod.h>
#include <linux/tegra_pm_domains.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/consumer.h>
#include <mach/tegra_usb_pad_ctrl.h>
#include <mach/io_dpd.h>
+#include <linux/pci-tegra.h>
#define PCI_CFG_SPACE_SIZE 256
#define PCI_EXT_CFG_SPACE_SIZE 4096
#define RP_LINK_CONTROL_STATUS_L0s_ENABLED 0x00000001
#define RP_LINK_CONTROL_STATUS_L1_ENABLED 0x00000002
+#define RP_LINK_CONTROL_STATUS_2 0x000000B0
+#define RP_LINK_CONTROL_STATUS_2_TRGT_LNK_SPD_MASK 0x0000000F
+#define RP_LINK_CONTROL_STATUS_2_TRGT_LNK_SPD_GEN1 0x00000001
+#define RP_LINK_CONTROL_STATUS_2_TRGT_LNK_SPD_GEN2 0x00000002
+
#define NV_PCIE2_RP_RSR 0x000000A0
#define NV_PCIE2_RP_RSR_PMESTAT (1 << 16)
};
#endif
+#if defined(CONFIG_ARCH_TEGRA_21x_SOC)
+static u32 rp_to_lane_map[] = {1, 0};
+#endif
+
struct tegra_pcie_soc_data {
unsigned int num_ports;
char **pcie_regulator_names;
* can result in the increase of the bootup time as there are big timeout
* loops.
*/
-#define TEGRA_PCIE_LINKUP_TIMEOUT 200 /* up to 1.2 seconds */
+#define TEGRA_PCIE_LINKUP_TIMEOUT 100 /* up to 100 ms */
static bool tegra_pcie_port_check_link(struct tegra_pcie_port *port)
{
unsigned int retries = 3;
do {
unsigned int timeout = TEGRA_PCIE_LINKUP_TIMEOUT;
- do {
- value = readl(port->base + RP_VEND_XP);
-
- if (value & RP_VEND_XP_DL_UP)
- break;
-
- usleep_range(1000, 2000);
- } while (--timeout);
-
- if (!timeout) {
- dev_info(port->pcie->dev, "link %u down, retrying\n",
- port->index);
- goto retry;
- }
-
- timeout = TEGRA_PCIE_LINKUP_TIMEOUT;
-
do {
value = readl(port->base + RP_LINK_CONTROL_STATUS);
-
if (value & RP_LINK_CONTROL_STATUS_DL_LINK_ACTIVE)
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);
} while (--retries);
if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT)
pdev->msi_enabled = 0;
} else {
+
+ /* Some of the old PCIe end points don't get enumerated
+ * if RP advertises both Gen-1 and Gen-2 speeds. Hence, the
+ * strategy followed here is to initially advertise only
+ * Gen-1 and after link is up, check end point's capability
+ * for Gen-2 and retrain link to Gen-2 speed
+ */
+ data = rp_readl(port, RP_LINK_CONTROL_STATUS_2);
+ data &= ~RP_LINK_CONTROL_STATUS_2_TRGT_LNK_SPD_MASK;
+ data |= RP_LINK_CONTROL_STATUS_2_TRGT_LNK_SPD_GEN1;
+ rp_writel(port, data, RP_LINK_CONTROL_STATUS_2);
+
/* Avoid warning during enumeration for invalid IRQ of RP */
data = rp_readl(port, NV_PCIE2_RP_INTR_BCR);
data |= NV_PCIE2_RP_INTR_BCR_INTR_LINE;
/*
- * Copyright (c) 2013-2015, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2013-2016, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
val |= XUSB_PADCTL_UPHY_MISC_PAD_P0_CTL1_AUX_RX_IDLE_TH;
writel(val, pad_base + misc_pad_ctl1_regs[lane]);
}
+
+bool tegra_phy_get_lane_rdet(u8 lane_num)
+{
+ u32 data;
+ void __iomem *pad_base = IO_ADDRESS(TEGRA_XUSB_PADCTL_BASE);
+
+ switch (lane_num) {
+ case 0:
+ data = readl(pad_base + XUSB_PADCTL_UPHY_MISC_PAD_P0_CTL1);
+ data = data &
+ XUSB_PADCTL_UPHY_MISC_PAD_P0_CTL1_AUX_TX_RDET_STATUS;
+ break;
+ case 1:
+ data = readl(pad_base + XUSB_PADCTL_UPHY_MISC_PAD_P1_CTL1);
+ data = data &
+ XUSB_PADCTL_UPHY_MISC_PAD_P1_CTL1_AUX_TX_RDET_STATUS;
+ break;
+ default:
+ return 0;
+ }
+ return !(!data);
+}
+EXPORT_SYMBOL_GPL(tegra_phy_get_lane_rdet);
#endif
static void tegra_pcie_lane_misc_pad_override(bool ovdr, int lane_owner)