summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Ziswiler <marcel.ziswiler@toradex.com>2016-11-09 18:21:06 +0100
committerMax Krummenacher <max.krummenacher@toradex.com>2017-01-11 20:59:49 +0100
commitc233fa95f0e2e3491256847b26e019dbe18881eb (patch)
tree9497e901366dab7a53c04a35a21efbc66be943a9
parentd97565599e341e9bda99c6ee109f8a66bd28cd24 (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.c14
-rw-r--r--arch/arm/mach-tegra/board-apalis_t30.h2
-rw-r--r--arch/arm/mach-tegra/pcie.c37
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;