diff options
author | Stephen Warren <swarren@nvidia.com> | 2013-05-06 16:19:19 -0400 |
---|---|---|
committer | Stephen Warren <swarren@nvidia.com> | 2013-08-13 14:07:56 -0400 |
commit | b4f173752a56187bd55752b0474429202f2ab1d3 (patch) | |
tree | 64b5936abc2c238f5114b42915ba3958c32890af /drivers/pci | |
parent | 0447cfd75a6bad561ebf2b393dcb2263c261b6c5 (diff) |
ARM: tegra: disable LP2 cpuidle state if PCIe is enabled
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 any PCIe devices with interrupts
are present. Detect this via the IRQ domain map operation. This is
slightly over-conservative; if a device with an interrupt is present but
the driver does not actually use them, LP2 will still be disabled.
However, this is a reasonable trade-off which enables a simpler
workaround.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Tested-by: Thierry Reding <treding@nvidia.com>
Acked-by: Thierry Reding <treding@nvidia.com>
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/host/pci-tegra.c | 5 |
1 files changed, 5 insertions, 0 deletions
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index ad95c406a6d0..7356741de36b 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/platform_device.h> | 41 | #include <linux/platform_device.h> |
42 | #include <linux/sizes.h> | 42 | #include <linux/sizes.h> |
43 | #include <linux/slab.h> | 43 | #include <linux/slab.h> |
44 | #include <linux/tegra-cpuidle.h> | ||
44 | #include <linux/tegra-powergate.h> | 45 | #include <linux/tegra-powergate.h> |
45 | #include <linux/vmalloc.h> | 46 | #include <linux/vmalloc.h> |
46 | #include <linux/regulator/consumer.h> | 47 | #include <linux/regulator/consumer.h> |
@@ -636,6 +637,8 @@ static int tegra_pcie_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin) | |||
636 | { | 637 | { |
637 | struct tegra_pcie *pcie = sys_to_pcie(pdev->bus->sysdata); | 638 | struct tegra_pcie *pcie = sys_to_pcie(pdev->bus->sysdata); |
638 | 639 | ||
640 | tegra_cpuidle_pcie_irqs_in_use(); | ||
641 | |||
639 | return pcie->irq; | 642 | return pcie->irq; |
640 | } | 643 | } |
641 | 644 | ||
@@ -1221,6 +1224,8 @@ static int tegra_msi_map(struct irq_domain *domain, unsigned int irq, | |||
1221 | irq_set_chip_data(irq, domain->host_data); | 1224 | irq_set_chip_data(irq, domain->host_data); |
1222 | set_irq_flags(irq, IRQF_VALID); | 1225 | set_irq_flags(irq, IRQF_VALID); |
1223 | 1226 | ||
1227 | tegra_cpuidle_pcie_irqs_in_use(); | ||
1228 | |||
1224 | return 0; | 1229 | return 0; |
1225 | } | 1230 | } |
1226 | 1231 | ||