提交 b8f44ec2 编写于 作者: K Kumar Gala

powerpc/fsl-pci: Fix MSI support on 83xx platforms

The following commit broke 83xx because it assumed the 83xx platforms
exposed the "IMMR" address in BAR0 like the 85xx/86xx/QoriQ devices do:

commit 3da34aae
Author: Kumar Gala <galak@kernel.crashing.org>
Date:   Tue May 12 15:51:56 2009 -0500

    powerpc/fsl: Support unique MSI addresses per PCIe Root Complex

However that is not true, so we have to search through the inbound
window settings on 83xx to find which one matches the IMMR address to
determine its PCI address.
Reported-by: NIlya Yanok <yanok@emcraft.com>
Signed-off-by: NKumar Gala <galak@kernel.crashing.org>
上级 4108d9ba
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <asm/ppc-pci.h> #include <asm/ppc-pci.h>
#include <asm/mpic.h> #include <asm/mpic.h>
#include "fsl_msi.h" #include "fsl_msi.h"
#include "fsl_pci.h"
LIST_HEAD(msi_head); LIST_HEAD(msi_head);
...@@ -125,13 +126,11 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq, ...@@ -125,13 +126,11 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq,
{ {
struct fsl_msi *msi_data = fsl_msi_data; struct fsl_msi *msi_data = fsl_msi_data;
struct pci_controller *hose = pci_bus_to_host(pdev->bus); struct pci_controller *hose = pci_bus_to_host(pdev->bus);
u32 base = 0; u64 base = fsl_pci_immrbar_base(hose);
pci_bus_read_config_dword(hose->bus, msg->address_lo = msi_data->msi_addr_lo + lower_32_bits(base);
PCI_DEVFN(0, 0), PCI_BASE_ADDRESS_0, &base); msg->address_hi = msi_data->msi_addr_hi + upper_32_bits(base);
msg->address_lo = msi_data->msi_addr_lo + base;
msg->address_hi = msi_data->msi_addr_hi;
msg->data = hwirq; msg->data = hwirq;
pr_debug("%s: allocated srs: %d, ibs: %d\n", pr_debug("%s: allocated srs: %d, ibs: %d\n",
......
/* /*
* MPC83xx/85xx/86xx PCI/PCIE support routing. * MPC83xx/85xx/86xx PCI/PCIE support routing.
* *
* Copyright 2007-2009 Freescale Semiconductor, Inc. * Copyright 2007-2010 Freescale Semiconductor, Inc.
* Copyright 2008-2009 MontaVista Software, Inc. * Copyright 2008-2009 MontaVista Software, Inc.
* *
* Initial author: Xianghua Xiao <x.xiao@freescale.com> * Initial author: Xianghua Xiao <x.xiao@freescale.com>
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
#include <sysdev/fsl_soc.h> #include <sysdev/fsl_soc.h>
#include <sysdev/fsl_pci.h> #include <sysdev/fsl_pci.h>
static int fsl_pcie_bus_fixup; static int fsl_pcie_bus_fixup, is_mpc83xx_pci;
static void __init quirk_fsl_pcie_header(struct pci_dev *dev) static void __init quirk_fsl_pcie_header(struct pci_dev *dev)
{ {
...@@ -430,6 +430,13 @@ struct mpc83xx_pcie_priv { ...@@ -430,6 +430,13 @@ struct mpc83xx_pcie_priv {
u32 dev_base; u32 dev_base;
}; };
struct pex_inbound_window {
u32 ar;
u32 tar;
u32 barl;
u32 barh;
};
/* /*
* With the convention of u-boot, the PCIE outbound window 0 serves * With the convention of u-boot, the PCIE outbound window 0 serves
* as configuration transactions outbound. * as configuration transactions outbound.
...@@ -437,6 +444,8 @@ struct mpc83xx_pcie_priv { ...@@ -437,6 +444,8 @@ struct mpc83xx_pcie_priv {
#define PEX_OUTWIN0_BAR 0xCA4 #define PEX_OUTWIN0_BAR 0xCA4
#define PEX_OUTWIN0_TAL 0xCA8 #define PEX_OUTWIN0_TAL 0xCA8
#define PEX_OUTWIN0_TAH 0xCAC #define PEX_OUTWIN0_TAH 0xCAC
#define PEX_RC_INWIN_BASE 0xE60
#define PEX_RCIWARn_EN 0x1
static int mpc83xx_pcie_exclude_device(struct pci_bus *bus, unsigned int devfn) static int mpc83xx_pcie_exclude_device(struct pci_bus *bus, unsigned int devfn)
{ {
...@@ -604,6 +613,8 @@ int __init mpc83xx_add_bridge(struct device_node *dev) ...@@ -604,6 +613,8 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
const int *bus_range; const int *bus_range;
int primary; int primary;
is_mpc83xx_pci = 1;
if (!of_device_is_available(dev)) { if (!of_device_is_available(dev)) {
pr_warning("%s: disabled by the firmware.\n", pr_warning("%s: disabled by the firmware.\n",
dev->full_name); dev->full_name);
...@@ -683,3 +694,40 @@ int __init mpc83xx_add_bridge(struct device_node *dev) ...@@ -683,3 +694,40 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
return ret; return ret;
} }
#endif /* CONFIG_PPC_83xx */ #endif /* CONFIG_PPC_83xx */
u64 fsl_pci_immrbar_base(struct pci_controller *hose)
{
#ifdef CONFIG_PPC_83xx
if (is_mpc83xx_pci) {
struct mpc83xx_pcie_priv *pcie = hose->dn->data;
struct pex_inbound_window *in;
int i;
/* Walk the Root Complex Inbound windows to match IMMR base */
in = pcie->cfg_type0 + PEX_RC_INWIN_BASE;
for (i = 0; i < 4; i++) {
/* not enabled, skip */
if (!in_le32(&in[i].ar) & PEX_RCIWARn_EN)
continue;
if (get_immrbase() == in_le32(&in[i].tar))
return (u64)in_le32(&in[i].barh) << 32 |
in_le32(&in[i].barl);
}
printk(KERN_WARNING "could not find PCI BAR matching IMMR\n");
}
#endif
#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
if (!is_mpc83xx_pci) {
u32 base;
pci_bus_read_config_dword(hose->bus,
PCI_DEVFN(0, 0), PCI_BASE_ADDRESS_0, &base);
return base;
}
#endif
return 0;
}
...@@ -88,6 +88,7 @@ struct ccsr_pci { ...@@ -88,6 +88,7 @@ struct ccsr_pci {
extern int fsl_add_bridge(struct device_node *dev, int is_primary); extern int fsl_add_bridge(struct device_node *dev, int is_primary);
extern void fsl_pcibios_fixup_bus(struct pci_bus *bus); extern void fsl_pcibios_fixup_bus(struct pci_bus *bus);
extern int mpc83xx_add_bridge(struct device_node *dev); extern int mpc83xx_add_bridge(struct device_node *dev);
u64 fsl_pci_immrbar_base(struct pci_controller *hose);
#endif /* __POWERPC_FSL_PCI_H */ #endif /* __POWERPC_FSL_PCI_H */
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册