diff options
author | Marcel Ziswiler <marcel.ziswiler@toradex.com> | 2016-11-09 18:21:06 +0100 |
---|---|---|
committer | Max Krummenacher <max.krummenacher@toradex.com> | 2017-01-11 20:59:49 +0100 |
commit | c233fa95f0e2e3491256847b26e019dbe18881eb (patch) | |
tree | 9497e901366dab7a53c04a35a21efbc66be943a9 | |
parent | d97565599e341e9bda99c6ee109f8a66bd28cd24 (diff) |
apalis_t30: fix pcie clock and reset not conforming to specification
Fix PCIe clock and reset not conforming to specification by moving PCIe
reset handling including the PLX PEX 8605 errata 5 workaround from the
board platform data into the right places timing wise in the PCIe driver
itself.
Also add a kernel command line argument to allow using the Apalis GPIO7
as a regular GPIO rather than for above mentioned PLX PEX 8605
workaround:
pex_perst=0
Signed-off-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>
Acked-by: Max Krummenacher <max.krummenacher@toradex.com>
-rw-r--r-- | arch/arm/mach-tegra/board-apalis_t30.c | 14 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board-apalis_t30.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-tegra/pcie.c | 37 |
3 files changed, 39 insertions, 14 deletions
diff --git a/arch/arm/mach-tegra/board-apalis_t30.c b/arch/arm/mach-tegra/board-apalis_t30.c index 4715676a877b..1142a84de7b0 100644 --- a/arch/arm/mach-tegra/board-apalis_t30.c +++ b/arch/arm/mach-tegra/board-apalis_t30.c @@ -830,20 +830,6 @@ static struct tegra_pci_platform_data apalis_t30_pci_platform_data = { static void apalis_t30_pci_init(void) { - /* Reset PLX PEX 8605 PCIe Switch plus PCIe devices on Apalis Evaluation - Board */ - gpio_request(PEX_PERST_N, "PEX_PERST_N"); - gpio_request(RESET_MOCI_N, "RESET_MOCI_N"); - gpio_direction_output(PEX_PERST_N, 0); - gpio_direction_output(RESET_MOCI_N, 0); - /* Must be asserted for 100 ms after power and clocks are stable */ - msleep(100); - 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 */ - mdelay(1); - gpio_set_value(RESET_MOCI_N, 1); - tegra_pci_device.dev.platform_data = &apalis_t30_pci_platform_data; platform_device_register(&tegra_pci_device); } diff --git a/arch/arm/mach-tegra/board-apalis_t30.h b/arch/arm/mach-tegra/board-apalis_t30.h index 14e003453fa7..55f7194415b7 100644 --- a/arch/arm/mach-tegra/board-apalis_t30.h +++ b/arch/arm/mach-tegra/board-apalis_t30.h @@ -26,6 +26,8 @@ #include <mach/gpio.h> #include <mach/irqs.h> +#include "gpio-names.h" + //#define FORCE_OFF_GPIO APALIS_GPIO6 //#define POWER_GPIO APALIS_GPIO5 diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c index 7765e56c6d39..6ef827598082 100644 --- a/arch/arm/mach-tegra/pcie.c +++ b/arch/arm/mach-tegra/pcie.c @@ -48,6 +48,10 @@ #include <mach/powergate.h> #include <mach/pci.h> +#ifdef CONFIG_MACH_APALIS_T30 +#include "board-apalis_t30.h" +#endif + #define MSELECT_CONFIG_0_ENABLE_PCIE_APERTURE 5 /* register definitions */ @@ -351,6 +355,21 @@ static u32 pex_controller_registers[] = { #endif }; +#ifdef CONFIG_MACH_APALIS_T30 +/* To disable the PCIe switch reset errata workaround */ +int g_pex_perst = 1; + +/* To disable the PCIe switch reset errata workaround */ +static int __init disable_pex_perst(char *s) +{ + if (!(*s) || !strcmp(s, "0")) + g_pex_perst = 0; + + return 0; +} +__setup("pex_perst=", disable_pex_perst); +#endif /* CONFIG_MACH_APALIS_T30 */ + static inline void afi_writel(u32 value, unsigned long offset) { writel(value, offset + AFI_OFFSET + tegra_pcie.regs); @@ -806,6 +825,15 @@ static void tegra_pcie_enable_controller(void) reg |= 1 << MSELECT_CONFIG_0_ENABLE_PCIE_APERTURE; writel(reg, reg_mselect_base); +#ifdef CONFIG_MACH_APALIS_T30 + /* 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); +#endif /* CONFIG_MACH_APALIS_T30 */ + /* Enable slot clock and ensure reset signals is assert */ for (i = 0; i < ARRAY_SIZE(pex_controller_registers); i++) { reg = pex_controller_registers[i]; @@ -883,6 +911,14 @@ static void tegra_pcie_enable_controller(void) afi_writel(val, reg); } +#ifdef CONFIG_MACH_APALIS_T30 + /* Must be asserted for 100 us 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); +#endif /* CONFIG_MACH_APALIS_T30 */ /* turn off IDDQ override */ val = pads_readl(PADS_CTL) & ~PADS_CTL_IDDQ_1L; @@ -1216,6 +1252,7 @@ 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; |