aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorKumar Gala <galak@kernel.crashing.org>2010-08-05 03:45:08 -0400
committerKumar Gala <galak@kernel.crashing.org>2010-10-14 01:52:30 -0400
commitb8f44ec2c05f9cfe1647173ac60c0cccb1118c91 (patch)
tree85a3dad04b89a5ba37e206dcb06a716ff4727924 /arch/powerpc
parent4108d9ba9091c55cfb968d42dd7dcae9a098b876 (diff)
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 3da34aae03d498ee62f75aa7467de93cce3030fd 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: Ilya Yanok <yanok@emcraft.com> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/sysdev/fsl_msi.c9
-rw-r--r--arch/powerpc/sysdev/fsl_pci.c52
-rw-r--r--arch/powerpc/sysdev/fsl_pci.h1
3 files changed, 55 insertions, 7 deletions
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index 87991d3abba..20cdcd2b0ee 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -24,6 +24,7 @@
24#include <asm/ppc-pci.h> 24#include <asm/ppc-pci.h>
25#include <asm/mpic.h> 25#include <asm/mpic.h>
26#include "fsl_msi.h" 26#include "fsl_msi.h"
27#include "fsl_pci.h"
27 28
28LIST_HEAD(msi_head); 29LIST_HEAD(msi_head);
29 30
@@ -125,13 +126,11 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq,
125{ 126{
126 struct fsl_msi *msi_data = fsl_msi_data; 127 struct fsl_msi *msi_data = fsl_msi_data;
127 struct pci_controller *hose = pci_bus_to_host(pdev->bus); 128 struct pci_controller *hose = pci_bus_to_host(pdev->bus);
128 u32 base = 0; 129 u64 base = fsl_pci_immrbar_base(hose);
129 130
130 pci_bus_read_config_dword(hose->bus, 131 msg->address_lo = msi_data->msi_addr_lo + lower_32_bits(base);
131 PCI_DEVFN(0, 0), PCI_BASE_ADDRESS_0, &base); 132 msg->address_hi = msi_data->msi_addr_hi + upper_32_bits(base);
132 133
133 msg->address_lo = msi_data->msi_addr_lo + base;
134 msg->address_hi = msi_data->msi_addr_hi;
135 msg->data = hwirq; 134 msg->data = hwirq;
136 135
137 pr_debug("%s: allocated srs: %d, ibs: %d\n", 136 pr_debug("%s: allocated srs: %d, ibs: %d\n",
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 4ae93322525..505c8f0ece9 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * MPC83xx/85xx/86xx PCI/PCIE support routing. 2 * MPC83xx/85xx/86xx PCI/PCIE support routing.
3 * 3 *
4 * Copyright 2007-2009 Freescale Semiconductor, Inc. 4 * Copyright 2007-2010 Freescale Semiconductor, Inc.
5 * Copyright 2008-2009 MontaVista Software, Inc. 5 * Copyright 2008-2009 MontaVista Software, Inc.
6 * 6 *
7 * Initial author: Xianghua Xiao <x.xiao@freescale.com> 7 * Initial author: Xianghua Xiao <x.xiao@freescale.com>
@@ -34,7 +34,7 @@
34#include <sysdev/fsl_soc.h> 34#include <sysdev/fsl_soc.h>
35#include <sysdev/fsl_pci.h> 35#include <sysdev/fsl_pci.h>
36 36
37static int fsl_pcie_bus_fixup; 37static int fsl_pcie_bus_fixup, is_mpc83xx_pci;
38 38
39static void __init quirk_fsl_pcie_header(struct pci_dev *dev) 39static void __init quirk_fsl_pcie_header(struct pci_dev *dev)
40{ 40{
@@ -430,6 +430,13 @@ struct mpc83xx_pcie_priv {
430 u32 dev_base; 430 u32 dev_base;
431}; 431};
432 432
433struct pex_inbound_window {
434 u32 ar;
435 u32 tar;
436 u32 barl;
437 u32 barh;
438};
439
433/* 440/*
434 * With the convention of u-boot, the PCIE outbound window 0 serves 441 * With the convention of u-boot, the PCIE outbound window 0 serves
435 * as configuration transactions outbound. 442 * as configuration transactions outbound.
@@ -437,6 +444,8 @@ struct mpc83xx_pcie_priv {
437#define PEX_OUTWIN0_BAR 0xCA4 444#define PEX_OUTWIN0_BAR 0xCA4
438#define PEX_OUTWIN0_TAL 0xCA8 445#define PEX_OUTWIN0_TAL 0xCA8
439#define PEX_OUTWIN0_TAH 0xCAC 446#define PEX_OUTWIN0_TAH 0xCAC
447#define PEX_RC_INWIN_BASE 0xE60
448#define PEX_RCIWARn_EN 0x1
440 449
441static int mpc83xx_pcie_exclude_device(struct pci_bus *bus, unsigned int devfn) 450static int mpc83xx_pcie_exclude_device(struct pci_bus *bus, unsigned int devfn)
442{ 451{
@@ -604,6 +613,8 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
604 const int *bus_range; 613 const int *bus_range;
605 int primary; 614 int primary;
606 615
616 is_mpc83xx_pci = 1;
617
607 if (!of_device_is_available(dev)) { 618 if (!of_device_is_available(dev)) {
608 pr_warning("%s: disabled by the firmware.\n", 619 pr_warning("%s: disabled by the firmware.\n",
609 dev->full_name); 620 dev->full_name);
@@ -683,3 +694,40 @@ err0:
683 return ret; 694 return ret;
684} 695}
685#endif /* CONFIG_PPC_83xx */ 696#endif /* CONFIG_PPC_83xx */
697
698u64 fsl_pci_immrbar_base(struct pci_controller *hose)
699{
700#ifdef CONFIG_PPC_83xx
701 if (is_mpc83xx_pci) {
702 struct mpc83xx_pcie_priv *pcie = hose->dn->data;
703 struct pex_inbound_window *in;
704 int i;
705
706 /* Walk the Root Complex Inbound windows to match IMMR base */
707 in = pcie->cfg_type0 + PEX_RC_INWIN_BASE;
708 for (i = 0; i < 4; i++) {
709 /* not enabled, skip */
710 if (!in_le32(&in[i].ar) & PEX_RCIWARn_EN)
711 continue;
712
713 if (get_immrbase() == in_le32(&in[i].tar))
714 return (u64)in_le32(&in[i].barh) << 32 |
715 in_le32(&in[i].barl);
716 }
717
718 printk(KERN_WARNING "could not find PCI BAR matching IMMR\n");
719 }
720#endif
721
722#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
723 if (!is_mpc83xx_pci) {
724 u32 base;
725
726 pci_bus_read_config_dword(hose->bus,
727 PCI_DEVFN(0, 0), PCI_BASE_ADDRESS_0, &base);
728 return base;
729 }
730#endif
731
732 return 0;
733}
diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h
index a9d8bbebed8..8ad72a11f77 100644
--- a/arch/powerpc/sysdev/fsl_pci.h
+++ b/arch/powerpc/sysdev/fsl_pci.h
@@ -88,6 +88,7 @@ struct ccsr_pci {
88extern int fsl_add_bridge(struct device_node *dev, int is_primary); 88extern int fsl_add_bridge(struct device_node *dev, int is_primary);
89extern void fsl_pcibios_fixup_bus(struct pci_bus *bus); 89extern void fsl_pcibios_fixup_bus(struct pci_bus *bus);
90extern int mpc83xx_add_bridge(struct device_node *dev); 90extern int mpc83xx_add_bridge(struct device_node *dev);
91u64 fsl_pci_immrbar_base(struct pci_controller *hose);
91 92
92#endif /* __POWERPC_FSL_PCI_H */ 93#endif /* __POWERPC_FSL_PCI_H */
93#endif /* __KERNEL__ */ 94#endif /* __KERNEL__ */