diff options
Diffstat (limited to 'arch/powerpc/sysdev/fsl_pci.c')
-rw-r--r-- | arch/powerpc/sysdev/fsl_pci.c | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 4ae933225251..32012a2e5a46 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -1,7 +1,7 @@ /* * 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. * * Initial author: Xianghua Xiao <x.xiao@freescale.com> @@ -310,6 +310,16 @@ void fsl_pcibios_fixup_bus(struct pci_bus *bus) } } +u64 fsl_pci_immrbar_base(struct pci_controller *hose) +{ + u32 base; + + pci_bus_read_config_dword(hose->bus, + PCI_DEVFN(0, 0), PCI_BASE_ADDRESS_0, &base); + + return base; +} + int __init fsl_add_bridge(struct device_node *dev, int is_primary) { int len; @@ -430,6 +440,13 @@ struct mpc83xx_pcie_priv { 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 * as configuration transactions outbound. @@ -437,6 +454,8 @@ struct mpc83xx_pcie_priv { #define PEX_OUTWIN0_BAR 0xCA4 #define PEX_OUTWIN0_TAL 0xCA8 #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) { @@ -463,6 +482,28 @@ static int mpc83xx_pcie_exclude_device(struct pci_bus *bus, unsigned int devfn) return PCIBIOS_SUCCESSFUL; } +/* Walk the Root Complex Inbound windows to match IMMR base */ +u64 fsl_pci_immrbar_base(struct pci_controller *hose) +{ + struct mpc83xx_pcie_priv *pcie = hose->dn->data; + struct pex_inbound_window *in = pcie->cfg_type0 + PEX_RC_INWIN_BASE; + int i; + + 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"); + + return 0; +} + static void __iomem *mpc83xx_pcie_remap_cfg(struct pci_bus *bus, unsigned int devfn, int offset) { |