summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-tegra')
-rw-r--r--arch/arm/mach-tegra/board-bonaire-pinmux.c2
-rw-r--r--arch/arm/mach-tegra/board-bonaire.c4
-rw-r--r--arch/arm/mach-tegra/pcie.c145
3 files changed, 109 insertions, 42 deletions
diff --git a/arch/arm/mach-tegra/board-bonaire-pinmux.c b/arch/arm/mach-tegra/board-bonaire-pinmux.c
index f432e309aa91..8f078c5b5222 100644
--- a/arch/arm/mach-tegra/board-bonaire-pinmux.c
+++ b/arch/arm/mach-tegra/board-bonaire-pinmux.c
@@ -50,7 +50,7 @@ static __initdata struct tegra_drive_pingroup_config bonaire_drive_pinmux[] = {
/* !!!FIXME!!!! POPULATE THIS TABLE */
static __initdata struct tegra_pingroup_config bonaire_pinmux[] = {
- DEFAULT_PINMUX(ULPI_DATA0, SPI3, NORMAL, TRISTATE, INPUT),
+ DEFAULT_PINMUX(ULPI_DATA0, SPI3, NORMAL, NORMAL, INPUT),
DEFAULT_PINMUX(ULPI_DATA1, SPI3, NORMAL, TRISTATE, INPUT),
DEFAULT_PINMUX(ULPI_DATA2, ULPI, NORMAL, NORMAL, INPUT),
DEFAULT_PINMUX(ULPI_DATA3, ULPI, NORMAL, NORMAL, INPUT),
diff --git a/arch/arm/mach-tegra/board-bonaire.c b/arch/arm/mach-tegra/board-bonaire.c
index 5a3fa69f84ef..be0b331a4788 100644
--- a/arch/arm/mach-tegra/board-bonaire.c
+++ b/arch/arm/mach-tegra/board-bonaire.c
@@ -570,8 +570,8 @@ static void __init bonaire_hs_uart_init(void)
static struct tegra_pci_platform_data bonaire_pcie_platform_data = {
.port_status[0] = 1,
.port_status[1] = 1,
- .use_dock_detect = 0,
- .gpio = 0,
+ .use_dock_detect = 1,
+ .gpio = TEGRA_GPIO_PO1,
};
static void bonaire_pcie_init(void)
diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c
index 7313f21fa458..7d4233a7728b 100644
--- a/arch/arm/mach-tegra/pcie.c
+++ b/arch/arm/mach-tegra/pcie.c
@@ -136,7 +136,16 @@
#define AFI_INTR_EN_FPCI_TIMEOUT (1 << 7)
#define AFI_INTR_EN_PRSNT_SENSE (1 << 8)
-#define AFI_PCIE_CONFIG 0x0f8
+#define AFI_PCIE_PME 0x0f0
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+#define AFI_PCIE_PME_TURN_OFF 0x10101
+#define AFI_PCIE_PME_ACK 0x40420
+#else
+#define AFI_PCIE_PME_TURN_OFF 0x101
+#define AFI_PCIE_PME_ACK 0x420
+#endif
+
+#define AFI_PCIE_CONFIG 0x0f8
#define AFI_PCIE_CONFIG_PCIEC0_DISABLE_DEVICE (1 << 1)
#define AFI_PCIE_CONFIG_PCIEC1_DISABLE_DEVICE (1 << 2)
#define AFI_PCIE_CONFIG_PCIEC2_DISABLE_DEVICE (1 << 3)
@@ -213,7 +222,8 @@
#define NV_PCIE2_RP_RSR_PMESTAT (1 << 16)
#define NV_PCIE2_RP_PRIV_MISC 0x00000FE0
-#define PCIE2_RP_PRIV_MISC_PRSNT_MAP (0xE << 0)
+#define PCIE2_RP_PRIV_MISC_PRSNT_MAP_EP_PRSNT (0xE << 0)
+#define PCIE2_RP_PRIV_MISC_PRSNT_MAP_EP_ABSNT (0xF << 0)
#define PCIE2_RP_PRIV_MISC_CTRL_CLK_CLAMP_THRESHOLD (0xF << 16)
#define PCIE2_RP_PRIV_MISC_CTLR_CLK_CLAMP_ENABLE (1 << 23)
#define PCIE2_RP_PRIV_MISC_TMS_CLK_CLAMP_THRESHOLD (0xF << 24)
@@ -363,6 +373,10 @@ static bool msi_enable;
/* this flag is used for enumeration by hotplug */
/* when dock is not connected while system boot */
static bool is_dock_conn_at_boot = true;
+/* used to identify if init is through boot or resume path */
+static bool is_resume_path;
+/* used to avoid successive hotplug disconnect or connect */
+static bool hotplug_event;
static inline void afi_writel(u32 value, unsigned long offset)
{
@@ -763,27 +777,55 @@ static void __init tegra_pcie_hotplug_init(void)
static int tegra_pcie_attach(void)
{
int err = 0;
+
+ if (!hotplug_event)
+ return err;
#ifdef CONFIG_PM
err = tegra_pcie_resume(NULL);
#endif
+ hotplug_event = false;
return err;
}
static int tegra_pcie_detach(void)
{
int err = 0;
+
+ if (hotplug_event)
+ return err;
#ifdef CONFIG_PM
err = tegra_pcie_suspend(NULL);
#endif
+ hotplug_event = true;
return err;
}
+#ifdef CONFIG_ARCH_TEGRA_12x_SOC
+static void tegra_pcie_prsnt_map_override(bool prsnt)
+{
+ unsigned int data;
+
+ if (hotplug_event)
+ return;
+ /* currently only hotplug on root port 0 supported */
+ PR_FUNC_LINE;
+ data = rp_readl(NV_PCIE2_RP_PRIV_MISC, 0);
+ data &= ~PCIE2_RP_PRIV_MISC_PRSNT_MAP_EP_ABSNT;
+ if (prsnt)
+ data |= PCIE2_RP_PRIV_MISC_PRSNT_MAP_EP_PRSNT;
+ else
+ data |= PCIE2_RP_PRIV_MISC_PRSNT_MAP_EP_ABSNT;
+ rp_writel(data, NV_PCIE2_RP_PRIV_MISC, 0);
+}
+#endif
+
static void __init work_hotplug_handler(struct work_struct *work)
{
struct tegra_pcie_info *pcie_driver =
container_of(work, struct tegra_pcie_info, hotplug_detect);
int val;
+ PR_FUNC_LINE;
if (pcie_driver->plat_data->gpio == -1)
return;
val = gpio_get_value(pcie_driver->plat_data->gpio);
@@ -792,12 +834,16 @@ static void __init work_hotplug_handler(struct work_struct *work)
tegra_pcie_attach();
} else {
pr_info("Pcie Dock DisConnected\n");
+#ifdef CONFIG_ARCH_TEGRA_12x_SOC
+ tegra_pcie_prsnt_map_override(false);
+#endif
tegra_pcie_detach();
}
}
static irqreturn_t gpio_pcie_detect_isr(int irq, void *arg)
{
+ PR_FUNC_LINE;
schedule_work(&tegra_pcie.hotplug_detect);
return IRQ_HANDLED;
}
@@ -1142,7 +1188,6 @@ static int tegra_pcie_enable_regulators(void)
return 0;
}
-#endif
static int tegra_pcie_disable_regulators(void)
{
@@ -1167,6 +1212,7 @@ static int tegra_pcie_disable_regulators(void)
err_exit:
return err;
}
+#endif
static int tegra_pcie_power_regate(void)
{
@@ -1209,6 +1255,47 @@ void tegra_pcie_unmap_resources(void)
tegra_pcie.regs = 0;
}
}
+
+static void tegra_pcie_pme_turnoff(void)
+{
+ unsigned int data;
+
+ data = afi_readl(AFI_PCIE_PME);
+ data |= AFI_PCIE_PME_TURN_OFF;
+ afi_writel(data, AFI_PCIE_PME);
+ do {
+ data = afi_readl(AFI_PCIE_PME);
+ } while (!(data & AFI_PCIE_PME_ACK));
+}
+
+#ifdef CONFIG_TEGRA_FPGA_PLATFORM
+static int tegra_pcie_fpga_phy_init(void)
+{
+#define CLK_RST_BOND_OUT_REG 0x60006078
+#define CLK_RST_BOND_OUT_REG_PCIE (1 << 6)
+#define FPGA_GEN2_SPEED_SUPPORT 0x90000001
+ int val = 0;
+
+ PR_FUNC_LINE;
+ val = readl(IO_ADDRESS(CLK_RST_BOND_OUT_REG));
+ /* return if current netlist does not contain PCIE */
+ if (val & CLK_RST_BOND_OUT_REG_PCIE)
+ return -ENODEV;
+
+ /* Do reset for FPGA pcie phy */
+ afi_writel(AFI_WR_SCRATCH_0_RESET_VAL, AFI_WR_SCRATCH_0);
+ udelay(10);
+ afi_writel(AFI_WR_SCRATCH_0_DEFAULT_VAL, AFI_WR_SCRATCH_0);
+ udelay(10);
+ afi_writel(AFI_WR_SCRATCH_0_RESET_VAL, AFI_WR_SCRATCH_0);
+
+ /* required for gen2 speed support on FPGA */
+ rp_writel(FPGA_GEN2_SPEED_SUPPORT, RP_VEND_XP_BIST, 0);
+
+ return 0;
+}
+#endif
+
static int tegra_pcie_power_off(void);
static int tegra_pcie_power_on(void)
@@ -1238,6 +1325,13 @@ static int tegra_pcie_power_on(void)
pr_err("PCIE: Failed to map resources\n");
goto err_exit;
}
+#ifdef CONFIG_TEGRA_FPGA_PLATFORM
+ err = tegra_pcie_fpga_phy_init();
+ if (err) {
+ pr_err("PCIE: Failed to initialize FPGA Phy\n");
+ goto err_exit;
+ }
+#endif
err_exit:
if (err)
@@ -1254,6 +1348,7 @@ static int tegra_pcie_power_off(void)
pr_debug("PCIE: Already powered off");
goto err_exit;
}
+ tegra_pcie_pme_turnoff();
tegra_pcie_unmap_resources();
if (tegra_pcie.pll_e)
clk_disable_unprepare(tegra_pcie.pll_e);
@@ -1262,8 +1357,11 @@ static int tegra_pcie_power_off(void)
if (err)
goto err_exit;
+#ifndef CONFIG_TEGRA_FPGA_PLATFORM
err = tegra_pcie_disable_regulators();
-
+ if (err)
+ goto err_exit;
+#endif
tegra_pcie.pcie_power_enabled = 0;
err_exit:
return err;
@@ -1399,7 +1497,8 @@ static void tegra_pcie_enable_clock_clamp(int index)
/* Power mangagement settings */
/* Enable clock clamping by default */
data = PCIE2_RP_PRIV_MISC_CTLR_CLK_CLAMP_ENABLE |
- PCIE2_RP_PRIV_MISC_PRSNT_MAP | PCIE2_RP_PRIV_MISC_CTRL_CLK_CLAMP_THRESHOLD |
+ PCIE2_RP_PRIV_MISC_PRSNT_MAP_EP_PRSNT |
+ PCIE2_RP_PRIV_MISC_CTRL_CLK_CLAMP_THRESHOLD |
PCIE2_RP_PRIV_MISC_TMS_CLK_CLAMP_ENABLE;
rp_writel(data, NV_PCIE2_RP_PRIV_MISC, index);
}
@@ -1462,39 +1561,11 @@ static void tegra_pcie_add_port(int index, u32 offset, u32 reset_reg)
tegra_pcie.num_ports++;
pp->index = index;
/* don't initialize root bus in resume path but boot path only */
- if (!msi_enable)
+ if (!is_resume_path)
pp->root_bus_nr = -1;
memset(pp->res, 0, sizeof(pp->res));
}
-#ifdef CONFIG_TEGRA_FPGA_PLATFORM
-static int tegra_pcie_fpga_phy_init(void)
-{
-#define CLK_RST_BOND_OUT_REG 0x60006078
-#define CLK_RST_BOND_OUT_REG_PCIE (1 << 6)
-#define FPGA_GEN2_SPEED_SUPPORT 0x90000001
- int val = 0;
-
- PR_FUNC_LINE;
- val = readl(IO_ADDRESS(CLK_RST_BOND_OUT_REG));
- /* return if current netlist does not contain PCIE */
- if (val & CLK_RST_BOND_OUT_REG_PCIE)
- return -ENODEV;
-
- /* Do reset for FPGA pcie phy */
- afi_writel(AFI_WR_SCRATCH_0_RESET_VAL, AFI_WR_SCRATCH_0);
- udelay(10);
- afi_writel(AFI_WR_SCRATCH_0_DEFAULT_VAL, AFI_WR_SCRATCH_0);
- udelay(10);
- afi_writel(AFI_WR_SCRATCH_0_RESET_VAL, AFI_WR_SCRATCH_0);
-
- /* required for gen2 speed support on FPGA */
- rp_writel(FPGA_GEN2_SPEED_SUPPORT, RP_VEND_XP_BIST, 0);
-
- return 0;
-}
-#endif
-
static int tegra_pcie_change_link_speed(struct pci_dev *pdev, bool isGen2)
{
u16 val, link_up_spd, link_dn_spd;
@@ -1588,11 +1659,6 @@ static int __init tegra_pcie_init(void)
if (err)
return err;
-#ifdef CONFIG_TEGRA_FPGA_PLATFORM
- err = tegra_pcie_fpga_phy_init();
- if (err)
- return err;
-#endif
err = tegra_pcie_enable_controller();
if (err)
return err;
@@ -1722,6 +1788,7 @@ static int tegra_pcie_resume(struct device *dev)
tegra_pcie_enable_controller();
tegra_pcie_setup_translations();
+ is_resume_path = true;
for (port = 0; port < MAX_PCIE_SUPPORTED_PORTS; port++) {
ctrl_offset += (port * 8);
rp_offset = (rp_offset + 0x1000) * port;