Skip to contentSkip to conversation

powerpc/fsl_pci: Add MPC83xx PCI-E controller RC mode support

PATCH Applied Anton Vorontsov 4 participants 8 messages Dec 29, 2008 – Jan 5, 2009

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 3/4 powerpc/fsl_pci: Add MPC83xx PCI-E controller RC mode support

This patch adds support for PCI-Express controllers as found on the newer MPC83xx chips.

The work is losely based on the Tony Li's patch[1], but unlike the original patch, this patch implements sliding window for the Type 1 configuration transactions, so we don't have to ioremap the whole PCI-E configuration space.

Since we have to remap the config space in the atomic context, and as ioremap() function might sleep, we use the fixmap API. With fixmap we can map the page-sized areas in the atomic context. The approch is similar to the x86 implementation (arch/x86/pci/mmconfig_32.c).

[1] http://ozlabs.org/pipermail/linuxppc-dev/2008-January/049028.html

---
 arch/powerpc/include/asm/fixmap.h     |    4 +
 arch/powerpc/include/asm/pci-bridge.h |    1 +
 arch/powerpc/sysdev/fsl_pci.c         |  200 ++++++++++++++++++++++++++++++++-
 include/linux/pci_ids.h               |    8 ++
 4 files changed, 209 insertions(+), 4 deletions(-)
arch/powerpc/include/asm/fixmap.h +4 -0
index 8428b38..982b738 100644
@@ -48,6 +48,10 @@ enum fixed_addresses {
 	FIX_KMAP_BEGIN,	/* reserved pte's for temporary kernel mappings */
 	FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
 #endif
+#if (defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x)) && \
+		defined(CONFIG_PCI)
+	FIX_MPC83XX_PCIE_CFG,
+#endif
 	/* FIX_PCIE_MCFG, */
 	__end_of_fixed_addresses
 };
arch/powerpc/include/asm/pci-bridge.h +1 -0
index 84007af..b4a9e68 100644
@@ -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
arch/powerpc/sysdev/fsl_pci.c +196 -4

251 lines not on this page · raw message

include/linux/pci_ids.h +8 -0
index 1800f1d..b30e28f 100644
@@ -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
Signature · 1 line
1.5.6.5
#1 lore raw
Quoted 8 lines · Anton Vorontsov

This patch adds support for PCI-Express controllers as found on the newer MPC83xx chips.

The work is losely based on the Tony Li's patch[1], but unlike the original patch, this patch implements sliding window for the Type 1 configuration transactions, so we don't have to ioremap the whole PCI-E configuration space.

Quoted 6 lines

Since we have to remap the config space in the atomic context, and as ioremap() function might sleep, we use the fixmap API. With fixmap we can map the page-sized areas in the atomic context. The approch is similar to the x86 implementation (arch/x86/pci/mmconfig_32.c).

[1] http://ozlabs.org/pipermail/linuxppc-dev/2008-January/049028.html

thanks for looking at cleaning this up. Have you looked at moving the outbound window as well? Its not a critical issue but something I was thinking about.

Quoted 17 lines

---

arch/powerpc/include/asm/fixmap.h     |    4 +
arch/powerpc/include/asm/pci-bridge.h |    1 +
arch/powerpc/sysdev/fsl_pci.c         |  200 ++++++++++++++++++++++++ 
++++++++-
include/linux/pci_ids.h               |    8 ++
4 files changed, 209 insertions(+), 4 deletions(-)
arch/powerpc/include/asm/fixmap.h +0 -0
index 8428b38..982b738 100644

arch/powerpc/include/asm/fixmap.h enum fixed_addresses { · line 54

Quoted 7 lines
arch/powerpc/include/asm/fixmap.h +4 -0
@@ -48,6 +48,10 @@ enum fixed_addresses {
 	FIX_KMAP_BEGIN,	/* reserved pte's for temporary kernel mappings */
 	FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
 #endif
+#if (defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x)) && \
+		defined(CONFIG_PCI)
+	FIX_MPC83XX_PCIE_CFG,
+#endif

Just use FIX_PCIE_MCFG that was the purpose and no big reason to ifdef this.

Quoted 302 lines
arch/powerpc/include/asm/fixmap.h +0 -0
 	/* FIX_PCIE_MCFG, */
 	__end_of_fixed_addresses
 };
arch/powerpc/include/asm/pci-bridge.h +1 -0
index 84007af..b4a9e68 100644
@@ -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
arch/powerpc/sysdev/fsl_pci.c +5 -1
index f611d03..2b6c341 100644
@@ -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 <[email protected]>
 * Recode: ZHANG WEI <[email protected]>
 * Rewrite the routing for Frescale PCI and PCI Express
 * 	Roy Zang <[email protected]>
+ * MPC83xx PCI-Express support:
+ * 	Tony Li <[email protected]>
+ * 	Anton Vorontsov <[email protected]>
 *
 * 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

arch/powerpc/sysdev/fsl_pci.c +4 -1
@@ -24,10 +28,10 @@
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
 #include <asm/machdep.h>
+#include <asm/fixmap.h>
 #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 +232,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);

arch/powerpc/sysdev/fsl_pci.c +102 -1
@@ -250,9 +262,173 @@ 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 {
+	struct resource cfg_res;
+	void __iomem *cfg_map;
+	int mapped_bus;
+	unsigned int mapped_devfn;
+};
+
+/*
+ * 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;
+	u32 bus_no = bus->number - hose->first_busno;
+	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->mapped_bus == bus_no && pcie->mapped_devfn == devfn)
+		goto mapped;
+
+	clear_fixmap(FIX_MPC83XX_PCIE_CFG);
+	set_fixmap_nocache(FIX_MPC83XX_PCIE_CFG,
+			   pcie->cfg_res.start + (devfn << 16));
+
+	out_le32(hose->cfg_data + PEX_OUTWIN0_TAL, bus_no);
+	out_le32(hose->cfg_data + PEX_OUTWIN0_TAH, 0);
+
+	pcie->mapped_devfn = devfn;
+	pcie->mapped_bus = bus_no;
+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,

arch/powerpc/sysdev/fsl_pci.c +63 -0
+				     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_res = *cfg;
+	pcie->cfg_map = (void __iomem *)fix_to_virt(FIX_MPC83XX_PCIE_CFG);
+	pcie->mapped_devfn = ~0;
+	pcie->mapped_bus = ~0;
+
+	WARN_ON(hose->dn->data);
+	hose->dn->data = pcie;
+
+	hose->cfg_data = ioremap(reg->start, resource_size(reg));
+	if (!hose->cfg_data)
+		goto err;
+
+	hose->indirect_type |= PPC_INDIRECT_TYPE_MPC83XX_PCIE;
+	hose->ops = &mpc83xx_pcie_ops;
+
+	if (fsl_pcie_check_link(hose))
+		hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK;
+
+	return 0;
+err:
+	kfree(pcie);
+	return -ENOMEM;
+
+}
+

int __init mpc83xx_add_bridge(struct device_node *dev)

{
	int len;
arch/powerpc/sysdev/fsl_pci.c +4 -0
@@ -262,6 +438,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 */
arch/powerpc/sysdev/fsl_pci.c +10 -1
@@ -309,7 +489,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",
arch/powerpc/sysdev/fsl_pci.c +3 -0
@@ -324,5 +513,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 */

include/linux/pci_ids.h +0 -0
index 1800f1d..b30e28f 100644
@@ -2209,6 +2209,14 @@
 #define PCI_DEVICE_ID_TDI_EHCI          0x0101

include/linux/pci_ids.h line 2219

Quoted 10 lines
include/linux/pci_ids.h +8 -0
 
 #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

Please make sure these get added to http://pci-ids.ucw.cz/

Quoted 6 lines
include/linux/pci_ids.h +0 -0
 #define PCI_DEVICE_ID_MPC8548E		0x0012
 #define PCI_DEVICE_ID_MPC8548		0x0013
 #define PCI_DEVICE_ID_MPC8543E		0x0014
Signature · 1 line
1.5.6.5
#2 lore raw

PATCH v2 3/4 powerpc/fsl_pci: Add MPC83xx PCI-E controller RC mode support

This patch adds support for PCI-Express controllers as found on the newer MPC83xx chips.

The work is loosely based on the Tony Li's patch[1], but unlike the original patch, this patch implements sliding window for the Type 1 transactions using outbound window translations, so we don't have to ioremap the whole PCI-E configuration space.

[1] http://ozlabs.org/pipermail/linuxppc-dev/2008-January/049028.html

---

Quoted 16 lines · Kumar Gala
Quoted 13 lines · Anton Vorontsov

This patch adds support for PCI-Express controllers as found on the newer MPC83xx chips.

The work is losely based on the Tony Li's patch[1], but unlike the original patch, this patch implements sliding window for the Type 1 configuration transactions, so we don't have to ioremap the whole PCI-E configuration space.

Since we have to remap the config space in the atomic context, and as ioremap() function might sleep, we use the fixmap API. With fixmap we can map the page-sized areas in the atomic context. The approch is similar to the x86 implementation (arch/x86/pci/mmconfig_32.c).

Quoted 5 lines
Quoted 1 line

[1] http://ozlabs.org/pipermail/linuxppc-dev/2008-January/049028.html

thanks for looking at cleaning this up. Have you looked at moving the outbound window as well? Its not a critical issue but something I was thinking about.

Ah, I think we can indeed slide the outbound window instead. That way we don't need the fixmap at all.

See how I change the PEX_OUTWIN0_TAL register in the new mpc83xx_pcie_remap_cfg:

According to specs, bits 7:2 are used to offset the register, bits 14:12 are used to denote a function, 19:15 are used for device number, 20:27 should specify bus number (original code was writing the bus number to the wrong bit field, I think).

So, we ioremap the first 4kb of the config space at the setup time, and then just changing the TAL to read/write config space of the needed BDF.

[...]

Quoted 3 lines
Quoted 1 line

+#define PCI_DEVICE_ID_MPC8377 0x00c7

Please make sure these get added to http://pci-ids.ucw.cz/

Will do.

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...

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(-)
arch/powerpc/include/asm/pci-bridge.h +1 -0
index 84007af..b4a9e68 100644
@@ -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
arch/powerpc/sysdev/fsl_pci.c +191 -4

243 lines not on this page · raw message

include/linux/pci_ids.h +8 -0
index 1800f1d..b30e28f 100644
@@ -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
Signature · 1 line
1.5.6.5
#3 lore raw
Quoted 3 lines

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.

Quoted 13 lines

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(-)
arch/powerpc/include/asm/pci-bridge.h +0 -0
index 84007af..b4a9e68 100644

arch/powerpc/include/asm/pci-bridge.h struct pci_controller { · line 135

Quoted 4 lines
arch/powerpc/include/asm/pci-bridge.h +1 -0
@@ -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.

Quoted 37 lines
arch/powerpc/include/asm/pci-bridge.h +0 -0
 	u32 indirect_type;
 #endif	/* !CONFIG_PPC64 */
 	/* Currently, we limit ourselves to 1 IO range and 3 mem
arch/powerpc/sysdev/fsl_pci.c +5 -1
index f611d03..9e104f8 100644
@@ -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 <[email protected]>
 * Recode: ZHANG WEI <[email protected]>
 * Rewrite the routing for Frescale PCI and PCI Express
 * 	Roy Zang <[email protected]>
+ * MPC83xx PCI-Express support:
+ * 	Tony Li <[email protected]>
+ * 	Anton Vorontsov <[email protected]>
 *
 * 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

arch/powerpc/sysdev/fsl_pci.c +0 -1
@@ -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)

arch/powerpc/sysdev/fsl_pci.c int __init fsl_add_bridge(struct device_node · line 233

Quoted 3 lines
arch/powerpc/sysdev/fsl_pci.c +0 -0
@@ -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?

Quoted 20 lines
arch/powerpc/sysdev/fsl_pci.c +4 -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);

arch/powerpc/sysdev/fsl_pci.c DECLARE_PCI_FIXUP_HEADER(0x1957, · line 267

Quoted 8 lines
arch/powerpc/sysdev/fsl_pci.c +1 -1
@@ -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 {

Quoted 229 lines
arch/powerpc/sysdev/fsl_pci.c +94 -0
+	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,

arch/powerpc/sysdev/fsl_pci.c +66 -0
+				     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;
arch/powerpc/sysdev/fsl_pci.c +4 -0
@@ -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 */
arch/powerpc/sysdev/fsl_pci.c +10 -1
@@ -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",
arch/powerpc/sysdev/fsl_pci.c +3 -0
@@ -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 */

include/linux/pci_ids.h +8 -0
index 1800f1d..b30e28f 100644
@@ -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
Signature · 1 line
1.5.6.5
#4 lore raw

PATCH v3 3/4 powerpc/fsl_pci: Add MPC83xx PCI-E controller RC mode support

This patch adds support for PCI-Express controllers as found on the newer MPC83xx chips.

The work is loosely based on the Tony Li's patch[1], but unlike the original patch, this patch implements sliding window for the Type 1 transactions using outbound window translations, so we don't have to ioremap the whole PCI-E configuration space.

[1] http://ozlabs.org/pipermail/linuxppc-dev/2008-January/049028.html

---

On Tue, Dec 30, 2008 at 12:07:08PM -0600, Kumar Gala wrote:
[...]

Quoted 10 lines

arch/powerpc/include/asm/pci-bridge.h struct pci_controller { · line 135

Quoted 7 lines
arch/powerpc/include/asm/pci-bridge.h +1 -0
@@ -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.

Quoted 3 lines

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.

Ugh, the PPC_INDIRECT_TYPE_MPC83XX_PCIE is a relic from the original patch, when HW bug workaround was in the board file(s). Now we don't need it as raw read/write pci ops are per phb, thus we already know that this is mpc83xx pcie controller.

Even if we'll need this information at some point in the board files, we can just use of_device_is_compatible().

Thanks for catching this.

[...]

Quoted 11 lines

arch/powerpc/include/asm/pci-bridge.h int __init fsl_add_bridge(struct device_node · line 233

Quoted 8 lines
arch/powerpc/include/asm/pci-bridge.h +0 -1
-#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)

arch/powerpc/include/asm/pci-bridge.h +0 -0
@@ -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?

No, we only need the fixups and fsl_pcie_check_link(). Though, I'll need to rearange the code to avoid new #ifdefs.

[...]

Quoted 4 lines

arch/powerpc/include/asm/pci-bridge.h int __init fsl_add_bridge(struct device_node · line 235

Quoted 2 lines
arch/powerpc/include/asm/pci-bridge.h +1 -0
 #if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x)
+struct mpc83xx_pcie {

should probably be something like struct pcie_window {

Well, I'd like to avoid _window, this struct might not neccesary describe only cfg window. It's just a private struct for mpc83xx pcie nodes, alike to driver_data for full fledged devices.

But I agree that "mpc83xx_pcie" name might be confusing (i.e. it might look like the struct describes mpc83xx pcie registers). Let's call it struct mpc83xx_pcie_priv?

Thanks for review, new version is down below.

 arch/powerpc/sysdev/fsl_pci.c |  234 ++++++++++++++++++++++++++++++++++++----
 include/linux/pci_ids.h       |    8 ++
 2 files changed, 218 insertions(+), 24 deletions(-)
arch/powerpc/sysdev/fsl_pci.c +210 -24
index f611d03..812dde3 100644
@@ -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 <[email protected]>
  * Recode: ZHANG WEI <[email protected]>
  * Rewrite the routing for Frescale PCI and PCI Express
  * 	Roy Zang <[email protected]>
+ * MPC83xx PCI-Express support:
+ * 	Tony Li <[email protected]>
+ * 	Anton Vorontsov <[email protected]>
  *
  * 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,6 +31,29 @@
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
 
+static int fsl_pcie_bus_fixup;
+
+static void __init quirk_fsl_pcie_header(struct pci_dev *dev)
+{
+	/* if we aren't a PCIe don't bother */
+	if (!pci_find_capability(dev, PCI_CAP_ID_EXP))
+		return;
+
+	dev->class = PCI_CLASS_BRIDGE_PCI << 8;
+	fsl_pcie_bus_fixup = 1;
+	return;
+}
+
+static int __init fsl_pcie_check_link(struct pci_controller *hose)
+{
+	u32 val;
+
+	early_read_config_dword(hose, 0, 0, PCIE_LTSSM, &val);
+	if (val < PCIE_LTSSM_L0)
+		return 1;
+	return 0;
+}
+
 #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,
@@ -118,28 +145,6 @@ static void __init setup_pci_pcsrbar(struct pci_controller *hose)
 #endif
 }
 
-static int fsl_pcie_bus_fixup;
-
-static void __init quirk_fsl_pcie_header(struct pci_dev *dev)
-{
-	/* if we aren't a PCIe don't bother */
-	if (!pci_find_capability(dev, PCI_CAP_ID_EXP))
-		return ;
-
-	dev->class = PCI_CLASS_BRIDGE_PCI << 8;
-	fsl_pcie_bus_fixup = 1;
-	return ;
-}
-
-static int __init fsl_pcie_check_link(struct pci_controller *hose)
-{
-	u32 val;
-	early_read_config_dword(hose, 0, 0, PCIE_LTSSM, &val);
-	if (val < PCIE_LTSSM_L0)
-		return 1;
-	return 0;
-}
-
 void fsl_pcibios_fixup_bus(struct pci_bus *bus)
 {
 	struct pci_controller *hose = (struct pci_controller *) bus->sysdata;
@@ -253,6 +258,171 @@ 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)
+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);
+
+struct mpc83xx_pcie_priv {
+	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 (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_priv *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;
+
+	/* 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 = {
+	.read = mpc83xx_pcie_read_config,
+	.write = mpc83xx_pcie_write_config,
+};
+
+static int __init mpc83xx_pcie_setup(struct pci_controller *hose,
+				     struct resource *reg,
+				     struct resource *cfg)
+{
+	struct mpc83xx_pcie_priv *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->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 +432,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 +483,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 +507,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 */
include/linux/pci_ids.h +8 -0
index 1800f1d..b30e28f 100644
@@ -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
Signature · 1 line
1.5.6.5
#5 lore raw

RE: [PATCH v2 3/4] powerpc/fsl_pci: Add MPC83xx PCI-E controller RCmode support

In reply to Anton Vorontsov

Review

Quoted 7 lines
(quoted diff) +7 -0
+static void __iomem *mpc83xx_pcie_remap_cfg(struct pci_bus *bus,
+				    unsigned int devfn, int offset)
+{
+	struct pci_controller *hose =3D bus->sysdata;
+	struct mpc83xx_pcie *pcie =3D hose->dn->data;
+	u8 bus_no =3D bus->number - hose->first_busno;
+	u32 dev_base =3D 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 =3D (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

#6 lore raw

Re: [PATCH v2 3/4] powerpc/fsl_pci: Add MPC83xx PCI-E controller RCmode support

kindly unsubscribe me from this mailing list.

#7 lore raw

Re: [PATCH v2 3/4] powerpc/fsl_pci: Add MPC83xx PCI-E controller RCmode support

In reply to Liu Dave
Quoted 10 lines · Liu Dave

arch/powerpc/sysdev/fsl_pci.c DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8536, quirk_fsl_pcie_header); · line 311

Quoted 7 lines
arch/powerpc/sysdev/fsl_pci.c +7 -0
+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,

Quoted 7 lines

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.

Quoted 2 lines

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,

Signature · 3 lines
Anton Vorontsov
email: [email protected]
irc://irc.freenode.net/bd2