Message ID | 20081229210559.GA10801@oksana.dev.rtsoft.ru (mailing list archive) |
---|---|
State | Changes Requested, archived |
Delegated to: | Kumar Gala |
Headers | show |
> How about this patch? It works for me using SKY2 NIC, though I don't > have any PCI-E switch or multi-function device to fully test the > sliding window behaviour... I'd prefer we tested under these scenarios but will not hold up the patch on it. > Thanks, > > arch/powerpc/include/asm/pci-bridge.h | 1 + > arch/powerpc/sysdev/fsl_pci.c | 195 ++++++++++++++++++++++++ > ++++++++- > include/linux/pci_ids.h | 8 ++ > 3 files changed, 200 insertions(+), 4 deletions(-) > > diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/ > include/asm/pci-bridge.h > index 84007af..b4a9e68 100644 > --- a/arch/powerpc/include/asm/pci-bridge.h > +++ b/arch/powerpc/include/asm/pci-bridge.h > @@ -132,6 +132,7 @@ struct pci_controller { > #define PPC_INDIRECT_TYPE_NO_PCIE_LINK 0x00000008 > #define PPC_INDIRECT_TYPE_BIG_ENDIAN 0x00000010 > #define PPC_INDIRECT_TYPE_BROKEN_MRM 0x00000020 > +#define PPC_INDIRECT_TYPE_MPC83XX_PCIE 0x00000040 we are bastardizing indirect_type w/this. 1. we just possibly rename this flags and have it generally available. 2. we should rename PPC_INDIRECT_TYPE_MPC83XX_PCIE to _BROKEN_.... 3. add a comment about what the new type is for. > > u32 indirect_type; > #endif /* !CONFIG_PPC64 */ > /* Currently, we limit ourselves to 1 IO range and 3 mem > diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/ > fsl_pci.c > index f611d03..9e104f8 100644 > --- a/arch/powerpc/sysdev/fsl_pci.c > +++ b/arch/powerpc/sysdev/fsl_pci.c > @@ -1,12 +1,16 @@ > /* > * MPC83xx/85xx/86xx PCI/PCIE support routing. > * > - * Copyright 2007,2008 Freescale Semiconductor, Inc > + * Copyright 2007-2009 Freescale Semiconductor, Inc. > + * Copyright 2008-2009 MontaVista Software, Inc. > * > * Initial author: Xianghua Xiao <x.xiao@freescale.com> > * Recode: ZHANG WEI <wei.zhang@freescale.com> > * Rewrite the routing for Frescale PCI and PCI Express > * Roy Zang <tie-fei.zang@freescale.com> > + * MPC83xx PCI-Express support: > + * Tony Li <tony.li@freescale.com> > + * Anton Vorontsov <avorontsov@ru.mvista.com> > * > * This program is free software; you can redistribute it and/or > modify it > * under the terms of the GNU General Public License as published > by the > @@ -27,7 +31,6 @@ > #include <sysdev/fsl_soc.h> > #include <sysdev/fsl_pci.h> > > -#if defined(CONFIG_PPC_85xx) || defined(CONFIG_PPC_86xx) > /* atmu setup for fsl pci/pcie controller */ > static void __init setup_pci_atmu(struct pci_controller *hose, > struct resource *rsrc) > @@ -228,6 +231,14 @@ int __init fsl_add_bridge(struct device_node > *dev, int is_primary) > return 0; > } I might just be missing the ctx in the patch, but is there a reason to expose setup_pci_atmu() on 83xx? > +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8314E, > quirk_fsl_pcie_header); > +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8314, > quirk_fsl_pcie_header); > +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8315E, > quirk_fsl_pcie_header); > +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8315, > quirk_fsl_pcie_header); > +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8377E, > quirk_fsl_pcie_header); > +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8377, > quirk_fsl_pcie_header); > +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8378E, > quirk_fsl_pcie_header); > +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8378, > quirk_fsl_pcie_header); > DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8548E, > quirk_fsl_pcie_header); > DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8548, > quirk_fsl_pcie_header); > DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8543E, > quirk_fsl_pcie_header); > @@ -250,9 +261,169 @@ DECLARE_PCI_FIXUP_HEADER(0x1957, > PCI_DEVICE_ID_MPC8536, quirk_fsl_pcie_header); > DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641, > quirk_fsl_pcie_header); > DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641D, > quirk_fsl_pcie_header); > DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8610, > quirk_fsl_pcie_header); > -#endif /* CONFIG_PPC_85xx || CONFIG_PPC_86xx */ > > #if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x) > +struct mpc83xx_pcie { should probably be something like struct pcie_window { > > + void __iomem *cfg_map; > + u32 dev_base; > +}; > + > +/* > + * With the convention of u-boot, the PCIE outbound window 0 serves > + * as configuration transactions outbound. > + */ > +#define PEX_OUTWIN0_TAL 0xCA8 > +#define PEX_OUTWIN0_TAH 0xCAC > + > +static int mpc83xx_pcie_exclude_device(struct pci_bus *bus, > unsigned int devfn) > +{ > + struct pci_controller *hose = bus->sysdata; > + > + if (hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK) > + return PCIBIOS_DEVICE_NOT_FOUND; > + /* > + * Workaround for the HW bug: for Type 0 configure transactions the > + * PCI-E controller does not check the device number bits and just > + * assumes that the device number bits are 0. > + */ > + if (hose->indirect_type & PPC_INDIRECT_TYPE_MPC83XX_PCIE) { > + if (bus->number == hose->first_busno || > + bus->primary == hose->first_busno) { > + if (devfn & 0xf8) > + return PCIBIOS_DEVICE_NOT_FOUND; > + } > + } > + > + if (ppc_md.pci_exclude_device) { > + if (ppc_md.pci_exclude_device(hose, bus->number, devfn)) > + return PCIBIOS_DEVICE_NOT_FOUND; > + } > + > + return PCIBIOS_SUCCESSFUL; > +} > + > +static void __iomem *mpc83xx_pcie_remap_cfg(struct pci_bus *bus, > + unsigned int devfn, int offset) > +{ > + struct pci_controller *hose = bus->sysdata; > + struct mpc83xx_pcie *pcie = hose->dn->data; > + u8 bus_no = bus->number - hose->first_busno; > + u32 dev_base = bus_no << 20 | devfn << 12; > + int ret; > + > + ret = mpc83xx_pcie_exclude_device(bus, devfn); > + if (ret) > + return NULL; > + > + offset &= 0xfff; > + > + if (hose->indirect_type & PPC_INDIRECT_TYPE_MPC83XX_PCIE) { > + /* Type 0 */ > + if (bus->number == hose->first_busno) > + return hose->cfg_data + offset; > + } > + > + if (pcie->dev_base == dev_base) > + goto mapped; > + > + out_le32(hose->cfg_data + PEX_OUTWIN0_TAL, dev_base); > + > + pcie->dev_base = dev_base; > +mapped: > + return pcie->cfg_map + offset; > +} > + > +static int mpc83xx_pcie_read_config(struct pci_bus *bus, unsigned > int devfn, > + int offset, int len, u32 *val) > +{ > + void __iomem *cfg_addr; > + > + cfg_addr = mpc83xx_pcie_remap_cfg(bus, devfn, offset); > + if (!cfg_addr) > + return PCIBIOS_DEVICE_NOT_FOUND; > + > + switch (len) { > + case 1: > + *val = in_8(cfg_addr); > + break; > + case 2: > + *val = in_le16(cfg_addr); > + break; > + default: > + *val = in_le32(cfg_addr); > + break; > + } > + > + return PCIBIOS_SUCCESSFUL; > +} > + > +static int mpc83xx_pcie_write_config(struct pci_bus *bus, unsigned > int devfn, > + int offset, int len, u32 val) > +{ > + void __iomem *cfg_addr; > + > + cfg_addr = mpc83xx_pcie_remap_cfg(bus, devfn, offset); > + if (!cfg_addr) > + return PCIBIOS_DEVICE_NOT_FOUND; > + > + switch (len) { > + case 1: > + out_8(cfg_addr, val); > + break; > + case 2: > + out_le16(cfg_addr, val); > + break; > + default: > + out_le32(cfg_addr, val); > + break; > + } > + > + return PCIBIOS_SUCCESSFUL; > +} > + > +static struct pci_ops mpc83xx_pcie_ops = { > + mpc83xx_pcie_read_config, > + mpc83xx_pcie_write_config, > +}; > + > +static int __init mpc83xx_pcie_setup(struct pci_controller *hose, > + struct resource *reg, > + struct resource *cfg) > +{ > + struct mpc83xx_pcie *pcie; > + > + pcie = zalloc_maybe_bootmem(sizeof(*pcie), GFP_KERNEL); > + if (!pcie) > + return -ENOMEM; > + > + pcie->cfg_map = ioremap(cfg->start, 0x1000); > + if (!pcie->cfg_map) > + goto err_cfg_map; > + > + hose->cfg_data = ioremap(reg->start, resource_size(reg)); > + if (!hose->cfg_data) > + goto err_cfg_data; > + > + WARN_ON(hose->dn->data); > + hose->dn->data = pcie; > + hose->indirect_type |= PPC_INDIRECT_TYPE_MPC83XX_PCIE; > + hose->ops = &mpc83xx_pcie_ops; > + > + out_le32(hose->cfg_data + PEX_OUTWIN0_TAH, 0); > + out_le32(hose->cfg_data + PEX_OUTWIN0_TAL, 0); > + > + if (fsl_pcie_check_link(hose)) > + hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK; > + > + return 0; > +err_cfg_data: > + iounmap(pcie->cfg_map); > +err_cfg_map: > + kfree(pcie); > + return -ENOMEM; > + > +} > + > int __init mpc83xx_add_bridge(struct device_node *dev) > { > int len; > @@ -262,6 +433,10 @@ int __init mpc83xx_add_bridge(struct > device_node *dev) > const int *bus_range; > int primary; > > + if (!of_device_is_available(dev)) { > + pr_warning("%s: disabled by the firmware.\n", dev->full_name); > + return -ENODEV; > + } > pr_debug("Adding PCI host bridge %s\n", dev->full_name); > > /* Fetch host bridge registers address */ > @@ -309,7 +484,16 @@ int __init mpc83xx_add_bridge(struct > device_node *dev) > hose->first_busno = bus_range ? bus_range[0] : 0; > hose->last_busno = bus_range ? bus_range[1] : 0xff; > > - setup_indirect_pci(hose, rsrc_cfg.start, rsrc_cfg.start + 4, 0); > + if (of_device_is_compatible(dev, "fsl,mpc8314-pcie")) { > + int ret; > + > + ret = mpc83xx_pcie_setup(hose, &rsrc_reg, &rsrc_cfg); > + if (ret) > + goto err; > + } else { > + setup_indirect_pci(hose, rsrc_cfg.start, > + rsrc_cfg.start + 4, 0); > + } > > printk(KERN_INFO "Found FSL PCI host bridge at 0x%016llx. " > "Firmware bus number: %d->%d\n", > @@ -324,5 +508,8 @@ int __init mpc83xx_add_bridge(struct device_node > *dev) > pci_process_bridge_OF_ranges(hose, dev, primary); > > return 0; > +err: > + pcibios_free_controller(hose); > + return -ENOMEM; > } > #endif /* CONFIG_PPC_83xx */ > diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h > index 1800f1d..b30e28f 100644 > --- a/include/linux/pci_ids.h > +++ b/include/linux/pci_ids.h > @@ -2209,6 +2209,14 @@ > #define PCI_DEVICE_ID_TDI_EHCI 0x0101 > > #define PCI_VENDOR_ID_FREESCALE 0x1957 > +#define PCI_DEVICE_ID_MPC8315E 0x00b4 > +#define PCI_DEVICE_ID_MPC8315 0x00b5 > +#define PCI_DEVICE_ID_MPC8314E 0x00b6 > +#define PCI_DEVICE_ID_MPC8314 0x00b7 > +#define PCI_DEVICE_ID_MPC8378E 0x00c4 > +#define PCI_DEVICE_ID_MPC8378 0x00c5 > +#define PCI_DEVICE_ID_MPC8377E 0x00c6 > +#define PCI_DEVICE_ID_MPC8377 0x00c7 > #define PCI_DEVICE_ID_MPC8548E 0x0012 > #define PCI_DEVICE_ID_MPC8548 0x0013 > #define PCI_DEVICE_ID_MPC8543E 0x0014 > -- > 1.5.6.5
> +static void __iomem *mpc83xx_pcie_remap_cfg(struct pci_bus *bus, > + unsigned int devfn, int offset) > +{ > + struct pci_controller *hose = bus->sysdata; > + struct mpc83xx_pcie *pcie = hose->dn->data; > + u8 bus_no = bus->number - hose->first_busno; > + u32 dev_base = bus_no << 20 | devfn << 12; Hello Anton, There is one bug for the bus/device number shift according to the latest 83xx UM. The shift should be dev_base = (bus_no << 24) | (devfn << 16); You can download the latest MPC8315 UM as reference from http://www.freescale.com. AFAIK, you will work on the u-boot for 83xx PEX, Any question forward to Jerry Huang (in cc). I think he should have some update for PEX. Thanks, Dave
kindly unsubscribe me from this mailing list.
On Mon, Jan 05, 2009 at 04:18:26PM +0800, Liu Dave wrote: > > +static void __iomem *mpc83xx_pcie_remap_cfg(struct pci_bus *bus, > > + unsigned int devfn, int offset) > > +{ > > + struct pci_controller *hose = bus->sysdata; > > + struct mpc83xx_pcie *pcie = hose->dn->data; > > + u8 bus_no = bus->number - hose->first_busno; > > + u32 dev_base = bus_no << 20 | devfn << 12; > > Hello Anton, > > There is one bug for the bus/device number shift according to the latest > 83xx UM. The shift should be > > dev_base = (bus_no << 24) | (devfn << 16); > > You can download the latest MPC8315 UM as reference from > http://www.freescale.com. Ah! Thanks a lot, that explains a lot. I was quite puzzled why FSL u-boots are using "wrong" shifts, so I "corrected" them. And indeed, I was looking at the old reference manual: MPC8315ERM Rev. 0 09/2007. The new manual (MPC8315ERM Rev. 1 2/2008) specifies other bits, the same as used in the FSL U-Boot, i.e. 31:24 for bus no, 23:19 and 18:16 for device and func. > AFAIK, you will work on the u-boot for 83xx PEX, Any question forward > to Jerry Huang (in cc). I think he should have some update for PEX. Much thanks for the information,
diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index 84007af..b4a9e68 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -132,6 +132,7 @@ struct pci_controller { #define PPC_INDIRECT_TYPE_NO_PCIE_LINK 0x00000008 #define PPC_INDIRECT_TYPE_BIG_ENDIAN 0x00000010 #define PPC_INDIRECT_TYPE_BROKEN_MRM 0x00000020 +#define PPC_INDIRECT_TYPE_MPC83XX_PCIE 0x00000040 u32 indirect_type; #endif /* !CONFIG_PPC64 */ /* Currently, we limit ourselves to 1 IO range and 3 mem diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index f611d03..9e104f8 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -1,12 +1,16 @@ /* * MPC83xx/85xx/86xx PCI/PCIE support routing. * - * Copyright 2007,2008 Freescale Semiconductor, Inc + * Copyright 2007-2009 Freescale Semiconductor, Inc. + * Copyright 2008-2009 MontaVista Software, Inc. * * Initial author: Xianghua Xiao <x.xiao@freescale.com> * Recode: ZHANG WEI <wei.zhang@freescale.com> * Rewrite the routing for Frescale PCI and PCI Express * Roy Zang <tie-fei.zang@freescale.com> + * MPC83xx PCI-Express support: + * Tony Li <tony.li@freescale.com> + * Anton Vorontsov <avorontsov@ru.mvista.com> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -27,7 +31,6 @@ #include <sysdev/fsl_soc.h> #include <sysdev/fsl_pci.h> -#if defined(CONFIG_PPC_85xx) || defined(CONFIG_PPC_86xx) /* atmu setup for fsl pci/pcie controller */ static void __init setup_pci_atmu(struct pci_controller *hose, struct resource *rsrc) @@ -228,6 +231,14 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary) return 0; } +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8314E, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8314, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8315E, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8315, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8377E, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8377, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8378E, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8378, quirk_fsl_pcie_header); DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8548E, quirk_fsl_pcie_header); DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8548, quirk_fsl_pcie_header); DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8543E, quirk_fsl_pcie_header); @@ -250,9 +261,169 @@ DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8536, quirk_fsl_pcie_header); DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641, quirk_fsl_pcie_header); DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641D, quirk_fsl_pcie_header); DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8610, quirk_fsl_pcie_header); -#endif /* CONFIG_PPC_85xx || CONFIG_PPC_86xx */ #if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x) +struct mpc83xx_pcie { + void __iomem *cfg_map; + u32 dev_base; +}; + +/* + * With the convention of u-boot, the PCIE outbound window 0 serves + * as configuration transactions outbound. + */ +#define PEX_OUTWIN0_TAL 0xCA8 +#define PEX_OUTWIN0_TAH 0xCAC + +static int mpc83xx_pcie_exclude_device(struct pci_bus *bus, unsigned int devfn) +{ + struct pci_controller *hose = bus->sysdata; + + if (hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK) + return PCIBIOS_DEVICE_NOT_FOUND; + /* + * Workaround for the HW bug: for Type 0 configure transactions the + * PCI-E controller does not check the device number bits and just + * assumes that the device number bits are 0. + */ + if (hose->indirect_type & PPC_INDIRECT_TYPE_MPC83XX_PCIE) { + if (bus->number == hose->first_busno || + bus->primary == hose->first_busno) { + if (devfn & 0xf8) + return PCIBIOS_DEVICE_NOT_FOUND; + } + } + + if (ppc_md.pci_exclude_device) { + if (ppc_md.pci_exclude_device(hose, bus->number, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + } + + return PCIBIOS_SUCCESSFUL; +} + +static void __iomem *mpc83xx_pcie_remap_cfg(struct pci_bus *bus, + unsigned int devfn, int offset) +{ + struct pci_controller *hose = bus->sysdata; + struct mpc83xx_pcie *pcie = hose->dn->data; + u8 bus_no = bus->number - hose->first_busno; + u32 dev_base = bus_no << 20 | devfn << 12; + int ret; + + ret = mpc83xx_pcie_exclude_device(bus, devfn); + if (ret) + return NULL; + + offset &= 0xfff; + + if (hose->indirect_type & PPC_INDIRECT_TYPE_MPC83XX_PCIE) { + /* Type 0 */ + if (bus->number == hose->first_busno) + return hose->cfg_data + offset; + } + + if (pcie->dev_base == dev_base) + goto mapped; + + out_le32(hose->cfg_data + PEX_OUTWIN0_TAL, dev_base); + + pcie->dev_base = dev_base; +mapped: + return pcie->cfg_map + offset; +} + +static int mpc83xx_pcie_read_config(struct pci_bus *bus, unsigned int devfn, + int offset, int len, u32 *val) +{ + void __iomem *cfg_addr; + + cfg_addr = mpc83xx_pcie_remap_cfg(bus, devfn, offset); + if (!cfg_addr) + return PCIBIOS_DEVICE_NOT_FOUND; + + switch (len) { + case 1: + *val = in_8(cfg_addr); + break; + case 2: + *val = in_le16(cfg_addr); + break; + default: + *val = in_le32(cfg_addr); + break; + } + + return PCIBIOS_SUCCESSFUL; +} + +static int mpc83xx_pcie_write_config(struct pci_bus *bus, unsigned int devfn, + int offset, int len, u32 val) +{ + void __iomem *cfg_addr; + + cfg_addr = mpc83xx_pcie_remap_cfg(bus, devfn, offset); + if (!cfg_addr) + return PCIBIOS_DEVICE_NOT_FOUND; + + switch (len) { + case 1: + out_8(cfg_addr, val); + break; + case 2: + out_le16(cfg_addr, val); + break; + default: + out_le32(cfg_addr, val); + break; + } + + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops mpc83xx_pcie_ops = { + mpc83xx_pcie_read_config, + mpc83xx_pcie_write_config, +}; + +static int __init mpc83xx_pcie_setup(struct pci_controller *hose, + struct resource *reg, + struct resource *cfg) +{ + struct mpc83xx_pcie *pcie; + + pcie = zalloc_maybe_bootmem(sizeof(*pcie), GFP_KERNEL); + if (!pcie) + return -ENOMEM; + + pcie->cfg_map = ioremap(cfg->start, 0x1000); + if (!pcie->cfg_map) + goto err_cfg_map; + + hose->cfg_data = ioremap(reg->start, resource_size(reg)); + if (!hose->cfg_data) + goto err_cfg_data; + + WARN_ON(hose->dn->data); + hose->dn->data = pcie; + hose->indirect_type |= PPC_INDIRECT_TYPE_MPC83XX_PCIE; + hose->ops = &mpc83xx_pcie_ops; + + out_le32(hose->cfg_data + PEX_OUTWIN0_TAH, 0); + out_le32(hose->cfg_data + PEX_OUTWIN0_TAL, 0); + + if (fsl_pcie_check_link(hose)) + hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK; + + return 0; +err_cfg_data: + iounmap(pcie->cfg_map); +err_cfg_map: + kfree(pcie); + return -ENOMEM; + +} + int __init mpc83xx_add_bridge(struct device_node *dev) { int len; @@ -262,6 +433,10 @@ int __init mpc83xx_add_bridge(struct device_node *dev) const int *bus_range; int primary; + if (!of_device_is_available(dev)) { + pr_warning("%s: disabled by the firmware.\n", dev->full_name); + return -ENODEV; + } pr_debug("Adding PCI host bridge %s\n", dev->full_name); /* Fetch host bridge registers address */ @@ -309,7 +484,16 @@ int __init mpc83xx_add_bridge(struct device_node *dev) hose->first_busno = bus_range ? bus_range[0] : 0; hose->last_busno = bus_range ? bus_range[1] : 0xff; - setup_indirect_pci(hose, rsrc_cfg.start, rsrc_cfg.start + 4, 0); + if (of_device_is_compatible(dev, "fsl,mpc8314-pcie")) { + int ret; + + ret = mpc83xx_pcie_setup(hose, &rsrc_reg, &rsrc_cfg); + if (ret) + goto err; + } else { + setup_indirect_pci(hose, rsrc_cfg.start, + rsrc_cfg.start + 4, 0); + } printk(KERN_INFO "Found FSL PCI host bridge at 0x%016llx. " "Firmware bus number: %d->%d\n", @@ -324,5 +508,8 @@ int __init mpc83xx_add_bridge(struct device_node *dev) pci_process_bridge_OF_ranges(hose, dev, primary); return 0; +err: + pcibios_free_controller(hose); + return -ENOMEM; } #endif /* CONFIG_PPC_83xx */ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 1800f1d..b30e28f 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2209,6 +2209,14 @@ #define PCI_DEVICE_ID_TDI_EHCI 0x0101 #define PCI_VENDOR_ID_FREESCALE 0x1957 +#define PCI_DEVICE_ID_MPC8315E 0x00b4 +#define PCI_DEVICE_ID_MPC8315 0x00b5 +#define PCI_DEVICE_ID_MPC8314E 0x00b6 +#define PCI_DEVICE_ID_MPC8314 0x00b7 +#define PCI_DEVICE_ID_MPC8378E 0x00c4 +#define PCI_DEVICE_ID_MPC8378 0x00c5 +#define PCI_DEVICE_ID_MPC8377E 0x00c6 +#define PCI_DEVICE_ID_MPC8377 0x00c7 #define PCI_DEVICE_ID_MPC8548E 0x0012 #define PCI_DEVICE_ID_MPC8548 0x0013 #define PCI_DEVICE_ID_MPC8543E 0x0014