diff options
Diffstat (limited to 'arch/arm/mach-tegra')
-rw-r--r-- | arch/arm/mach-tegra/cpuidle-tegra20.c | 12 | ||||
-rw-r--r-- | arch/arm/mach-tegra/cpuidle.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-tegra/cpuidle.h | 1 |
3 files changed, 23 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/cpuidle-tegra20.c b/arch/arm/mach-tegra/cpuidle-tegra20.c index 706aa4215c36..b82dcaee2ef4 100644 --- a/arch/arm/mach-tegra/cpuidle-tegra20.c +++ b/arch/arm/mach-tegra/cpuidle-tegra20.c @@ -211,6 +211,18 @@ static int tegra20_idle_lp2_coupled(struct cpuidle_device *dev, } #endif +/* + * Tegra20 HW appears to have a bug such that PCIe device interrupts, whether + * they are legacy IRQs or MSI, are lost when LP2 is enabled. To work around + * this, simply disable LP2 if the PCI driver and DT node are both enabled. + */ +void tegra20_cpuidle_pcie_irqs_in_use(void) +{ + pr_info_once( + "Disabling cpuidle LP2 state, since PCIe IRQs are in use\n"); + tegra_idle_driver.states[1].disabled = true; +} + int __init tegra20_cpuidle_init(void) { return cpuidle_register(&tegra_idle_driver, cpu_possible_mask); diff --git a/arch/arm/mach-tegra/cpuidle.c b/arch/arm/mach-tegra/cpuidle.c index e85973cef037..0961dfcf83a4 100644 --- a/arch/arm/mach-tegra/cpuidle.c +++ b/arch/arm/mach-tegra/cpuidle.c @@ -44,3 +44,13 @@ void __init tegra_cpuidle_init(void) break; } } + +void tegra_cpuidle_pcie_irqs_in_use(void) +{ + switch (tegra_chip_id) { + case TEGRA20: + if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC)) + tegra20_cpuidle_pcie_irqs_in_use(); + break; + } +} diff --git a/arch/arm/mach-tegra/cpuidle.h b/arch/arm/mach-tegra/cpuidle.h index 9ec2c1ab0fa4..c017dab60ffa 100644 --- a/arch/arm/mach-tegra/cpuidle.h +++ b/arch/arm/mach-tegra/cpuidle.h @@ -19,6 +19,7 @@ #ifdef CONFIG_CPU_IDLE int tegra20_cpuidle_init(void); +void tegra20_cpuidle_pcie_irqs_in_use(void); int tegra30_cpuidle_init(void); int tegra114_cpuidle_init(void); void tegra_cpuidle_init(void); |