mirror of https://gitee.com/openkylin/linux.git
Merge branch 'pci/host-tegra' into next
* pci/host-tegra: PCI: tegra: Do not allocate MSI target memory PCI: tegra: Support MSI 64-bit addressing
This commit is contained in:
commit
1fb3d7d5e1
|
@ -233,8 +233,8 @@ struct tegra_msi {
|
||||||
struct msi_controller chip;
|
struct msi_controller chip;
|
||||||
DECLARE_BITMAP(used, INT_PCI_MSI_NR);
|
DECLARE_BITMAP(used, INT_PCI_MSI_NR);
|
||||||
struct irq_domain *domain;
|
struct irq_domain *domain;
|
||||||
unsigned long pages;
|
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
|
u64 phys;
|
||||||
int irq;
|
int irq;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1448,9 +1448,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 +1498,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;
|
||||||
|
|
||||||
|
@ -1531,12 +1529,25 @@ static int tegra_pcie_enable_msi(struct tegra_pcie *pcie)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* setup AFI/FPCI range */
|
/*
|
||||||
msi->pages = __get_free_pages(GFP_KERNEL, 0);
|
* The PCI host bridge on Tegra contains some logic that intercepts
|
||||||
base = virt_to_phys((void *)msi->pages);
|
* MSI writes, which means that the MSI target address doesn't have
|
||||||
|
* to point to actual physical memory. Rather than allocating one 4
|
||||||
|
* KiB page of system memory that's never used, we can simply pick
|
||||||
|
* an arbitrary address within an area reserved for system memory
|
||||||
|
* in the FPCI address map.
|
||||||
|
*
|
||||||
|
* However, in order to avoid confusion, we pick an address that
|
||||||
|
* doesn't map to physical memory. The FPCI address map reserves a
|
||||||
|
* 1012 GiB region for system memory and memory-mapped I/O. Since
|
||||||
|
* none of the Tegra SoCs that contain this PCI host bridge can
|
||||||
|
* address more than 16 GiB of system memory, the last 4 KiB of
|
||||||
|
* these 1012 GiB is a good candidate.
|
||||||
|
*/
|
||||||
|
msi->phys = 0xfcfffff000;
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
@ -1585,8 +1596,6 @@ static int tegra_pcie_disable_msi(struct tegra_pcie *pcie)
|
||||||
afi_writel(pcie, 0, AFI_MSI_EN_VEC6);
|
afi_writel(pcie, 0, AFI_MSI_EN_VEC6);
|
||||||
afi_writel(pcie, 0, AFI_MSI_EN_VEC7);
|
afi_writel(pcie, 0, AFI_MSI_EN_VEC7);
|
||||||
|
|
||||||
free_pages(msi->pages, 0);
|
|
||||||
|
|
||||||
if (msi->irq > 0)
|
if (msi->irq > 0)
|
||||||
free_irq(msi->irq, pcie);
|
free_irq(msi->irq, pcie);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue