diff options
Diffstat (limited to 'drivers/pci/host/pci-tegra.c')
-rw-r--r-- | drivers/pci/host/pci-tegra.c | 33 |
1 files changed, 21 insertions, 12 deletions
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index 0dadb81eca70..b3722b7709df 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c | |||
@@ -233,8 +233,8 @@ struct tegra_msi { | |||
233 | struct msi_controller chip; | 233 | struct msi_controller chip; |
234 | DECLARE_BITMAP(used, INT_PCI_MSI_NR); | 234 | DECLARE_BITMAP(used, INT_PCI_MSI_NR); |
235 | struct irq_domain *domain; | 235 | struct irq_domain *domain; |
236 | unsigned long pages; | ||
237 | struct mutex lock; | 236 | struct mutex lock; |
237 | u64 phys; | ||
238 | int irq; | 238 | int irq; |
239 | }; | 239 | }; |
240 | 240 | ||
@@ -1448,9 +1448,8 @@ static int tegra_msi_setup_irq(struct msi_controller *chip, | |||
1448 | 1448 | ||
1449 | irq_set_msi_desc(irq, desc); | 1449 | irq_set_msi_desc(irq, desc); |
1450 | 1450 | ||
1451 | msg.address_lo = virt_to_phys((void *)msi->pages); | 1451 | msg.address_lo = lower_32_bits(msi->phys); |
1452 | /* 32 bit address only */ | 1452 | msg.address_hi = upper_32_bits(msi->phys); |
1453 | msg.address_hi = 0; | ||
1454 | msg.data = hwirq; | 1453 | msg.data = hwirq; |
1455 | 1454 | ||
1456 | pci_write_msi_msg(irq, &msg); | 1455 | pci_write_msi_msg(irq, &msg); |
@@ -1499,7 +1498,6 @@ static int tegra_pcie_enable_msi(struct tegra_pcie *pcie) | |||
1499 | const struct tegra_pcie_soc *soc = pcie->soc; | 1498 | const struct tegra_pcie_soc *soc = pcie->soc; |
1500 | struct tegra_msi *msi = &pcie->msi; | 1499 | struct tegra_msi *msi = &pcie->msi; |
1501 | struct device *dev = pcie->dev; | 1500 | struct device *dev = pcie->dev; |
1502 | unsigned long base; | ||
1503 | int err; | 1501 | int err; |
1504 | u32 reg; | 1502 | u32 reg; |
1505 | 1503 | ||
@@ -1531,12 +1529,25 @@ static int tegra_pcie_enable_msi(struct tegra_pcie *pcie) | |||
1531 | goto err; | 1529 | goto err; |
1532 | } | 1530 | } |
1533 | 1531 | ||
1534 | /* setup AFI/FPCI range */ | 1532 | /* |
1535 | msi->pages = __get_free_pages(GFP_KERNEL, 0); | 1533 | * The PCI host bridge on Tegra contains some logic that intercepts |
1536 | base = virt_to_phys((void *)msi->pages); | 1534 | * MSI writes, which means that the MSI target address doesn't have |
1535 | * to point to actual physical memory. Rather than allocating one 4 | ||
1536 | * KiB page of system memory that's never used, we can simply pick | ||
1537 | * an arbitrary address within an area reserved for system memory | ||
1538 | * in the FPCI address map. | ||
1539 | * | ||
1540 | * However, in order to avoid confusion, we pick an address that | ||
1541 | * doesn't map to physical memory. The FPCI address map reserves a | ||
1542 | * 1012 GiB region for system memory and memory-mapped I/O. Since | ||
1543 | * none of the Tegra SoCs that contain this PCI host bridge can | ||
1544 | * address more than 16 GiB of system memory, the last 4 KiB of | ||
1545 | * these 1012 GiB is a good candidate. | ||
1546 | */ | ||
1547 | msi->phys = 0xfcfffff000; | ||
1537 | 1548 | ||
1538 | afi_writel(pcie, base >> soc->msi_base_shift, AFI_MSI_FPCI_BAR_ST); | 1549 | afi_writel(pcie, msi->phys >> soc->msi_base_shift, AFI_MSI_FPCI_BAR_ST); |
1539 | afi_writel(pcie, base, AFI_MSI_AXI_BAR_ST); | 1550 | afi_writel(pcie, msi->phys, AFI_MSI_AXI_BAR_ST); |
1540 | /* this register is in 4K increments */ | 1551 | /* this register is in 4K increments */ |
1541 | afi_writel(pcie, 1, AFI_MSI_BAR_SZ); | 1552 | afi_writel(pcie, 1, AFI_MSI_BAR_SZ); |
1542 | 1553 | ||
@@ -1585,8 +1596,6 @@ static int tegra_pcie_disable_msi(struct tegra_pcie *pcie) | |||
1585 | afi_writel(pcie, 0, AFI_MSI_EN_VEC6); | 1596 | afi_writel(pcie, 0, AFI_MSI_EN_VEC6); |
1586 | afi_writel(pcie, 0, AFI_MSI_EN_VEC7); | 1597 | afi_writel(pcie, 0, AFI_MSI_EN_VEC7); |
1587 | 1598 | ||
1588 | free_pages(msi->pages, 0); | ||
1589 | |||
1590 | if (msi->irq > 0) | 1599 | if (msi->irq > 0) |
1591 | free_irq(msi->irq, pcie); | 1600 | free_irq(msi->irq, pcie); |
1592 | 1601 | ||