summaryrefslogtreecommitdiff
path: root/drivers/pci/host/pci-tegra.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/host/pci-tegra.c')
-rw-r--r--drivers/pci/host/pci-tegra.c149
1 files changed, 114 insertions, 35 deletions
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
index 1ef5791a892b..e0e7998f57f3 100644
--- a/drivers/pci/host/pci-tegra.c
+++ b/drivers/pci/host/pci-tegra.c
@@ -282,6 +282,10 @@ struct tegra_pcie_info {
struct regulator *regulator_hvdd;
struct regulator *regulator_pexio;
struct regulator *regulator_avdd_plle;
+#ifdef CONFIG_MACH_APALIS_TK1
+ struct regulator *regulator_apalis_tk1_ldo9;
+ struct regulator *regulator_apalis_tk1_ldo10;
+#endif /* CONFIG_MACH_APALIS_TK1 */
struct clk *pcie_xclk;
struct clk *pcie_mselect;
struct clk *pcie_emc;
@@ -976,25 +980,87 @@ static int tegra_pcie_enable_pads(bool enable)
return err;
}
-static int tegra_pcie_enable_controller(void)
+static void tegra_pcie_port_reset(struct tegra_pcie_port *pp, u32 reset_reg)
{
- u32 val, reg;
- int i, ret = 0, lane_owner;
+ u32 reg;
PR_FUNC_LINE;
-
#ifdef CONFIG_MACH_APALIS_TK1
/* Reset PLX PEX 8605 PCIe Switch plus PCIe devices on Apalis Evaluation
Board */
- if (g_pex_perst) gpio_request(PEX_PERST_N, "PEX_PERST_N");
- gpio_request(RESET_MOCI_N, "RESET_MOCI_N");
if (g_pex_perst) gpio_direction_output(PEX_PERST_N, 0);
- gpio_direction_output(RESET_MOCI_N, 0);
+ gpio_direction_output(RESET_MOCI_CTRL, 0);
/* Reset I210 Gigabit Ethernet Controller */
- gpio_request(LAN_RESET_N, "LAN_RESET_N");
gpio_direction_output(LAN_RESET_N, 0);
+
+ /*
+ * Make sure we don't get any back feeding from LAN_WAKE_N resp.
+ * DEV_OFF_N
+ */
+ gpio_direction_output(LAN_WAKE_N, 0);
+ gpio_direction_output(LAN_DEV_OFF_N, 0);
+
+ /* Make sure LDO9 and LDO10 are initially disabled @ 0V */
+ if (regulator_is_enabled(tegra_pcie.regulator_apalis_tk1_ldo9))
+ regulator_disable(tegra_pcie.regulator_apalis_tk1_ldo9);
+ if (regulator_is_enabled(tegra_pcie.regulator_apalis_tk1_ldo10))
+ regulator_disable(tegra_pcie.regulator_apalis_tk1_ldo10);
+
+ mdelay(100);
+
+ /* Make sure LAN_WAKE_N gets re-configured as a GPIO input */
+ gpio_direction_input(LAN_WAKE_N);
+
+ /* Make sure controller gets enabled by disabling DEV_OFF_N */
+ gpio_set_value(LAN_DEV_OFF_N, 1);
+
+ /*
+ * Enable LDO9 and LDO10 for +V3.3_ETH on patched prototype
+ * V1.0A and sample V1.0B and newer modules
+ */
+ if (regulator_enable(tegra_pcie.regulator_apalis_tk1_ldo9) < 0) {
+ pr_err("pcie: couldn't enable regulator i210_vdd3p3_ldo9\n");
+ return;
+ }
+ if (regulator_enable(tegra_pcie.regulator_apalis_tk1_ldo10) < 0) {
+ pr_err("pcie: couldn't enable regulator i210_vdd3p3_ldo10\n");
+ return;
+ }
+#endif /* CONFIG_MACH_APALIS_TK1 */
+
+ /* Pulse the PEX reset */
+ reg = afi_readl(reset_reg) & ~AFI_PEX_CTRL_RST;
+ afi_writel(reg, reset_reg);
+
+ /* Must be asserted for 100 ms after power and clocks are stable */
+ mdelay(100);
+
+ reg = afi_readl(reset_reg) | AFI_PEX_CTRL_RST;
+ afi_writel(reg, reset_reg);
+
+#ifdef CONFIG_MACH_APALIS_TK1
+ gpio_set_value(LAN_RESET_N, 1);
+
+ if (g_pex_perst) gpio_set_value(PEX_PERST_N, 1);
+ /* Err_5: PEX_REFCLK_OUTpx/nx Clock Outputs is not Guaranteed Until
+ 900 us After PEX_PERST# De-assertion */
+ if (g_pex_perst) mdelay(1);
+ gpio_set_value(RESET_MOCI_CTRL, 1);
+
+ /* Release I210 Gigabit Ethernet Controller Reset */
+ gpio_set_value(LAN_RESET_N, 1);
#endif /* CONFIG_MACH_APALIS_TK1 */
+}
+
+static int tegra_pcie_enable_controller(void)
+{
+ u32 val, reg;
+ int i, ret = 0, lane_owner;
+ struct tegra_pcie_port *pp;
+ int ctrl_offset = AFI_PEX0_CTRL;
+
+ PR_FUNC_LINE;
/* Enable slot clock and ensure reset signal is assert */
for (i = 0; i < ARRAY_SIZE(pex_controller_registers); i++) {
@@ -1071,25 +1137,12 @@ static int tegra_pcie_enable_controller(void)
/* Wait for clock to latch (min of 100us) */
udelay(100);
- /* deassert PEX reset signal */
- for (i = 0; i < ARRAY_SIZE(pex_controller_registers); i++) {
- val = afi_readl(pex_controller_registers[i]);
- val |= AFI_PEX_CTRL_RST;
- afi_writel(val, pex_controller_registers[i]);
+ pp = tegra_pcie.port + tegra_pcie.num_ports;
+ for (i = 0; i < MAX_PCIE_SUPPORTED_PORTS; i++) {
+ ctrl_offset += (i * 8);
+ tegra_pcie_port_reset(pp, ctrl_offset);
}
-#ifdef CONFIG_MACH_APALIS_TK1
- /* Must be asserted for 100 ms after power and clocks are stable */
- if (g_pex_perst) gpio_set_value(PEX_PERST_N, 1);
- /* Err_5: PEX_REFCLK_OUTpx/nx Clock Outputs is not Guaranteed Until
- 900 us After PEX_PERST# De-assertion */
- if (g_pex_perst) mdelay(1);
- gpio_set_value(RESET_MOCI_N, 1);
-
- /* Release I210 Gigabit Ethernet Controller Reset */
- gpio_set_value(LAN_RESET_N, 1);
-#endif /* CONFIG_MACH_APALIS_TK1 */
-
return ret;
}
@@ -1138,12 +1191,37 @@ static int tegra_pcie_enable_regulators(void)
tegra_pcie.regulator_avdd_plle = 0;
}
}
+
+#ifdef CONFIG_MACH_APALIS_TK1
+ if (tegra_pcie.regulator_apalis_tk1_ldo9 == NULL) {
+ tegra_pcie.regulator_apalis_tk1_ldo9 = regulator_get(tegra_pcie.dev, "i210_vdd3p3_ldo9");
+ if (IS_ERR(tegra_pcie.regulator_apalis_tk1_ldo9)) {
+ pr_err("pcie: couldn't get regulator i210_vdd3p3_ldo9\n");
+ tegra_pcie.regulator_apalis_tk1_ldo9 = 0;
+ }
+ }
+
+ if (tegra_pcie.regulator_apalis_tk1_ldo10 == NULL) {
+ tegra_pcie.regulator_apalis_tk1_ldo10 = regulator_get(tegra_pcie.dev, "i210_vdd3p3_ldo10");
+ if (IS_ERR(tegra_pcie.regulator_apalis_tk1_ldo10)) {
+ pr_err("pcie: couldn't get regulator i210_vdd3p3_ldo10\n");
+ tegra_pcie.regulator_apalis_tk1_ldo10 = 0;
+ }
+ }
+#endif /* CONFIG_MACH_APALIS_TK1 */
+
if (tegra_pcie.regulator_hvdd)
ret = regulator_enable(tegra_pcie.regulator_hvdd);
if (tegra_pcie.regulator_pexio)
ret = regulator_enable(tegra_pcie.regulator_pexio);
if (tegra_pcie.regulator_avdd_plle)
ret = regulator_enable(tegra_pcie.regulator_avdd_plle);
+#ifdef CONFIG_MACH_APALIS_TK1
+ if (tegra_pcie.regulator_apalis_tk1_ldo9)
+ ret = regulator_enable(tegra_pcie.regulator_apalis_tk1_ldo9);
+ if (tegra_pcie.regulator_apalis_tk1_ldo10)
+ ret = regulator_enable(tegra_pcie.regulator_apalis_tk1_ldo10);
+#endif /* CONFIG_MACH_APALIS_TK1 */
return 0;
}
@@ -1506,16 +1584,8 @@ static bool tegra_pcie_check_link(struct tegra_pcie_port *pp, int idx,
}
retry:
- if (--retries) {
- /* Pulse the PEX reset */
-/* TBD: timing not as per PCIe spec */
- reg = afi_readl(reset_reg) & ~AFI_PEX_CTRL_RST;
- afi_writel(reg, reset_reg);
- reg = afi_readl(reset_reg) | AFI_PEX_CTRL_RST;
- afi_writel(reg, reset_reg);
- }
-
- } while (retries);
+ tegra_pcie_port_reset(pp, reset_reg);
+ } while (--retries);
return false;
}
@@ -1943,6 +2013,15 @@ static int __init tegra_pcie_init(void)
tegra_pcie_power_off(false);
return err;
}
+
+#ifdef CONFIG_MACH_APALIS_TK1
+ gpio_request(LAN_DEV_OFF_N, "LAN_DEV_OFF_N");
+ gpio_request(LAN_RESET_N, "LAN_RESET_N");
+ gpio_request(LAN_WAKE_N, "LAN_WAKE_N");
+ if (g_pex_perst) gpio_request(PEX_PERST_N, "PEX_PERST_N");
+ gpio_request(RESET_MOCI_CTRL, "RESET_MOCI_CTRL");
+#endif /* CONFIG_MACH_APALIS_TK1 */
+
err = tegra_pcie_enable_controller();
if (err) {
pr_err("PCIE: enable controller failed\n");