diff options
Diffstat (limited to 'drivers/pci/host/pci-tegra.c')
-rw-r--r-- | drivers/pci/host/pci-tegra.c | 149 |
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"); |