Commit c0165550 authored by Thierry Reding's avatar Thierry Reding Committed by Bjorn Helgaas

PCI: tegra: Support MSI 64-bit addressing

The MSI target address can reside beyond the 32-bit boundary on devices
with more than 2 GiB of system memory.  The PCI host bridge on Tegra can
easily support 64-bit addresses, so make sure to pass the upper 32 bits of
the target address to endpoints when allocating MSI entries.
Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Acked-by: default avatarStephen Warren <swarren@nvidia.com>
parent 769b461f
...@@ -235,6 +235,7 @@ struct tegra_msi { ...@@ -235,6 +235,7 @@ struct tegra_msi {
struct irq_domain *domain; struct irq_domain *domain;
unsigned long pages; unsigned long pages;
struct mutex lock; struct mutex lock;
u64 phys;
int irq; int irq;
}; };
...@@ -1448,9 +1449,8 @@ static int tegra_msi_setup_irq(struct msi_controller *chip, ...@@ -1448,9 +1449,8 @@ static int tegra_msi_setup_irq(struct msi_controller *chip,
irq_set_msi_desc(irq, desc); irq_set_msi_desc(irq, desc);
msg.address_lo = virt_to_phys((void *)msi->pages); msg.address_lo = lower_32_bits(msi->phys);
/* 32 bit address only */ msg.address_hi = upper_32_bits(msi->phys);
msg.address_hi = 0;
msg.data = hwirq; msg.data = hwirq;
pci_write_msi_msg(irq, &msg); pci_write_msi_msg(irq, &msg);
...@@ -1499,7 +1499,6 @@ static int tegra_pcie_enable_msi(struct tegra_pcie *pcie) ...@@ -1499,7 +1499,6 @@ static int tegra_pcie_enable_msi(struct tegra_pcie *pcie)
const struct tegra_pcie_soc *soc = pcie->soc; const struct tegra_pcie_soc *soc = pcie->soc;
struct tegra_msi *msi = &pcie->msi; struct tegra_msi *msi = &pcie->msi;
struct device *dev = pcie->dev; struct device *dev = pcie->dev;
unsigned long base;
int err; int err;
u32 reg; u32 reg;
...@@ -1533,10 +1532,10 @@ static int tegra_pcie_enable_msi(struct tegra_pcie *pcie) ...@@ -1533,10 +1532,10 @@ static int tegra_pcie_enable_msi(struct tegra_pcie *pcie)
/* setup AFI/FPCI range */ /* setup AFI/FPCI range */
msi->pages = __get_free_pages(GFP_KERNEL, 0); msi->pages = __get_free_pages(GFP_KERNEL, 0);
base = virt_to_phys((void *)msi->pages); msi->phys = virt_to_phys((void *)msi->pages);
afi_writel(pcie, base >> soc->msi_base_shift, AFI_MSI_FPCI_BAR_ST); afi_writel(pcie, msi->phys >> soc->msi_base_shift, AFI_MSI_FPCI_BAR_ST);
afi_writel(pcie, base, AFI_MSI_AXI_BAR_ST); afi_writel(pcie, msi->phys, AFI_MSI_AXI_BAR_ST);
/* this register is in 4K increments */ /* this register is in 4K increments */
afi_writel(pcie, 1, AFI_MSI_BAR_SZ); afi_writel(pcie, 1, AFI_MSI_BAR_SZ);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment