Subject: [PATCH 1/3] ppc: Update PPC440SPe support

From: Stefan Roese <[email-masked]>
Date: Mon, 2 Apr 2007 11:09:46 +0200

ppc: Update PPC440SPe support

This patch updates the AMCC 440SPe support in arch/ppc. It's done in
preparation for the support of the new AMCC 440SPe eval board
katmai.

Signed-off-by: Stefan Roese <[email-masked]>

---
commit c268079210504e5c5a2ae94aa449aa244545ba22
tree ff46ca68445236f1d359be13e814ea1046acb083
parent 2e175a90047a2dbc76fde169c990164895b25dfc
author Stefan Roese <[email-masked]> Mon, 02 Apr 2007 10:44:13 +0200
committer Stefan Roese <[email-masked]> Mon, 02 Apr 2007 10:44:13 +0200

 arch/ppc/platforms/4xx/ppc440spe.c |  242 ++++++++++++++++
 arch/ppc/platforms/4xx/ppc440spe.h |   29 +-
 arch/ppc/syslib/Makefile           |    6 
 arch/ppc/syslib/ppc440spe_pcie.c   |  549 ++++++++++++++++++++++++++++--------
 arch/ppc/syslib/ppc440spe_pcie.h   |   16 +
 include/asm-ppc/ibm44x.h           |   11 +
 6 files changed, 709 insertions(+), 144 deletions(-)

diff --git a/arch/ppc/platforms/4xx/ppc440spe.c b/arch/ppc/platforms/4xx/ppc440spe.c
index 1be5d1c..9f3954c 100644
--- a/arch/ppc/platforms/4xx/ppc440spe.c
+++ b/arch/ppc/platforms/4xx/ppc440spe.c
@@ -22,6 +22,13 @@
 #include <asm/ocp.h>
 #include <asm/ppc4xx_pic.h>
 
+#if defined(CONFIG_AMCC_PPC440SPE_ADMA)
+#include <syslib/ppc440spe_pcie.h>
+#include <linux/async_tx.h>
+#include <linux/platform_device.h>
+#include <asm/ppc440spe_adma.h>
+#endif
+
 static struct ocp_func_emac_data ppc440spe_emac0_def = {
 	.rgmii_idx	= -1,		/* No RGMII */
 	.rgmii_mux	= -1,		/* No RGMII */
@@ -129,18 +136,247 @@ struct ocp_def core_ocp[] = {
 struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = {
 	{ .polarity     = 0xffffffff,
 	  .triggering   = 0x010f0004,
-	  .ext_irq_mask = 0x00000000,
+	  .ext_irq_mask = 0x00402000,	/* IRQ15, IRQ14 */
 	},
 	{ .polarity     = 0xffffffff,
 	  .triggering   = 0x001f8040,
-	  .ext_irq_mask = 0x00007c30,   /* IRQ6 - IRQ7, IRQ8 - IRQ12 */
+	  .ext_irq_mask = 0x80007c30,   /* IRQ13, IRQ12 - IRQ8, IRQ7 - IRQ6 */
 	},
 	{ .polarity     = 0xffffffff,
 	  .triggering   = 0x00000000,
-	  .ext_irq_mask = 0x000000fc,   /* IRQ0 - IRQ5 */
+	  .ext_irq_mask = 0x000000fc,   /* IRQ5 - IRQ0 */
 	},
 	{ .polarity     = 0xffffffff,
 	  .triggering   = 0x00000000,
 	  .ext_irq_mask = 0x00000000,
 	},
 };
+
+#if defined(CONFIG_AMCC_PPC440SPE_ADMA)
+
+static u64 ppc440spe_adma_dmamask = DMA_32BIT_MASK;
+
+/* DMA and XOR platform devices' resources */
+static struct resource ppc440spe_dma_0_resources[] = {
+	{
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = DMA0_CS_FIFO_NEED_SERVICE,
+		.end = DMA0_CS_FIFO_NEED_SERVICE,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+static struct resource ppc440spe_dma_1_resources[] = {
+	{
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = DMA1_CS_FIFO_NEED_SERVICE,
+		.end = DMA1_CS_FIFO_NEED_SERVICE,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+static struct resource ppc440spe_xor_resources[] = {
+	{
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = XOR_INTERRUPT,
+		.end = XOR_INTERRUPT,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+/* DMA and XOR platform devices' data */
+static struct ppc440spe_adma_platform_data ppc440spe_dma_0_data = {
+	.hw_id  = PPC440SPE_DMA0_ID,
+	.capabilities = DMA_CAP_MEMCPY | DMA_CAP_INTERRUPT,
+	.pool_size = PAGE_SIZE,
+};
+
+static struct ppc440spe_adma_platform_data ppc440spe_dma_1_data = {
+	.hw_id  = PPC440SPE_DMA1_ID,
+	.capabilities =  DMA_CAP_MEMCPY | DMA_CAP_INTERRUPT,
+	.pool_size = PAGE_SIZE,
+};
+
+static struct ppc440spe_adma_platform_data ppc440spe_xor_data = {
+	.hw_id  = PPC440SPE_XOR_ID,
+	.capabilities = DMA_CAP_XOR | DMA_CAP_INTERRUPT,
+	.pool_size = PAGE_SIZE,
+};
+
+/* DMA and XOR platform devices definitions */
+static struct platform_device ppc440spe_dma_0_channel = {
+	.name = "PPC440SPE-ADMA",
+	.id = PPC440SPE_DMA0_ID,
+	.num_resources = ARRAY_SIZE(ppc440spe_dma_0_resources),
+	.resource = ppc440spe_dma_0_resources,
+	.dev = {
+		.dma_mask = &ppc440spe_adma_dmamask,
+		.coherent_dma_mask = DMA_64BIT_MASK,
+		.platform_data = (void *) &ppc440spe_dma_0_data,
+	},
+};
+
+static struct platform_device ppc440spe_dma_1_channel = {
+	.name = "PPC440SPE-ADMA",
+	.id = PPC440SPE_DMA1_ID,
+	.num_resources = ARRAY_SIZE(ppc440spe_dma_1_resources),
+	.resource = ppc440spe_dma_1_resources,
+	.dev = {
+		.dma_mask = &ppc440spe_adma_dmamask,
+		.coherent_dma_mask = DMA_64BIT_MASK,
+		.platform_data = (void *) &ppc440spe_dma_1_data,
+	},
+};
+
+static struct platform_device ppc440spe_xor_channel = {
+	.name = "PPC440SPE-ADMA",
+	.id = PPC440SPE_XOR_ID,
+	.num_resources = ARRAY_SIZE(ppc440spe_xor_resources),
+	.resource = ppc440spe_xor_resources,
+	.dev = {
+		.dma_mask = &ppc440spe_adma_dmamask,
+		.coherent_dma_mask = DMA_64BIT_MASK,
+		.platform_data = (void *) &ppc440spe_xor_data,
+	},
+};
+
+/*
+ *  Init DMA0/1 and XOR engines; allocate memory for DMAx FIFOs; set platform_device
+ * memory resources addresses
+ */
+static void ppc440spe_configure_raid_devices(void)
+{
+	void *fifo_buf;
+	i2o_regs_t *i2o_reg;
+	dma_regs_t *dma_reg0, *dma_reg1;
+	xor_regs_t *xor_reg;
+	u32 mask;
+
+	/*
+	 * Map registers and allocate fifo buffer
+	 */
+	if (!(i2o_reg  = ioremap(I2O_MMAP_BASE, I2O_MMAP_SIZE))) {
+		printk(KERN_ERR "I2O registers mapping failed.\n");
+		return;
+	}
+	if (!(dma_reg0 = ioremap(DMA0_MMAP_BASE, DMA_MMAP_SIZE))) {
+		printk(KERN_ERR "DMA0 registers mapping failed.\n");
+		goto err1;
+	}
+	if (!(dma_reg1 = ioremap(DMA1_MMAP_BASE, DMA_MMAP_SIZE))) {
+		printk(KERN_ERR "DMA1 registers mapping failed.\n");
+		goto err2;
+	}
+	if (!(xor_reg  = ioremap(XOR_MMAP_BASE,XOR_MMAP_SIZE))) {
+		printk(KERN_ERR "XOR registers mapping failed.\n");
+		goto err3;
+	}
+
+	/*  Provide memory regions for DMA's FIFOs: I2O, DMA0 and DMA1 share
+	 * the base address of FIFO memory space.
+	 *  Actually we need twice more physical memory than programmed in the
+	 * <fsiz> register (because there are two FIFOs foreach DMA: CP and CS)
+	 */
+	fifo_buf = kmalloc((DMA0_FIFO_SIZE + DMA1_FIFO_SIZE)<<1, GFP_KERNEL);
+	if (!fifo_buf) {
+		printk(KERN_ERR "DMA FIFO buffer allocating failed.\n");
+		goto err4;
+	}
+
+	/*
+	 * Configure h/w
+	 */
+	/* Reset I2O/DMA */
+	SDR_WRITE(DCRN_SDR_SRST, DCRN_SDR_SRST_I2ODMA);
+	SDR_WRITE(DCRN_SDR_SRST, 0);
+
+	/* Reset XOR */
+	out_be32(&xor_reg->crsr, XOR_CRSR_XASR_BIT);
+	out_be32(&xor_reg->crrr, XOR_CRSR_64BA_BIT);
+
+	/* Setup the base address of mmaped registers */
+	mtdcr(DCRN_I2O0_IBAH, (u32)(I2O_MMAP_BASE >> 32));
+	mtdcr(DCRN_I2O0_IBAL, (u32)(I2O_MMAP_BASE) | I2O_REG_ENABLE);
+
+	/* SetUp FIFO memory space base address */
+	out_le32(&i2o_reg->ifbah, 0);
+	out_le32(&i2o_reg->ifbal, ((u32)__pa(fifo_buf)));
+
+	/* set zero FIFO size for I2O, so the whole fifo_buf is used by DMAs.
+	 * DMA0_FIFO_SIZE is defined in bytes, <fsiz> - in number of CDB pointers (8byte).
+	 * DMA FIFO Length = CSlength + CPlength, where
+	 *  CSlength = CPlength = (fsiz + 1) * 8.
+	 */
+	out_le32(&i2o_reg->ifsiz, 0);
+	out_le32(&dma_reg0->fsiz, DMA_FIFO_ENABLE | ((DMA0_FIFO_SIZE>>3) - 2));
+	out_le32(&dma_reg1->fsiz, DMA_FIFO_ENABLE | ((DMA1_FIFO_SIZE>>3) - 2));
+
+	/* Configure DMA engine */
+	out_le32(&dma_reg0->cfg, DMA_CFG_DXEPR_HP | DMA_CFG_DFMPP_HP | DMA_CFG_FALGN);
+	out_le32(&dma_reg1->cfg, DMA_CFG_DXEPR_HP | DMA_CFG_DFMPP_HP | DMA_CFG_FALGN);
+
+	/* Clear Status */
+	out_le32(&dma_reg0->dsts, ~0);
+	out_le32(&dma_reg1->dsts, ~0);
+
+	/* Unmask 'CS FIFO Attention' interrupts */
+	mask = in_le32(&i2o_reg->iopim) & ~(I2O_IOPIM_P0SNE | I2O_IOPIM_P1SNE);
+	out_le32(&i2o_reg->iopim, mask);
+
+	/* enable XOR engine interrupt */
+	out_be32(&xor_reg->ier, XOR_IE_CBCIE_BIT);
+
+	/*
+	 * Unmap I2O registers
+	 */
+	iounmap(i2o_reg);
+
+	/*
+	 * Set resource addresses
+	 */
+	ppc440spe_dma_0_channel.resource[0].start = (resource_size_t)(dma_reg0);
+	ppc440spe_dma_0_channel.resource[0].end =
+		ppc440spe_dma_0_channel.resource[0].start+DMA_MMAP_SIZE;
+
+	ppc440spe_dma_1_channel.resource[0].start = (resource_size_t)(dma_reg1);
+	ppc440spe_dma_1_channel.resource[0].end =
+		ppc440spe_dma_1_channel.resource[0].start+DMA_MMAP_SIZE;
+
+	ppc440spe_xor_channel.resource[0].start = (resource_size_t)(xor_reg);
+	ppc440spe_xor_channel.resource[0].end =
+		ppc440spe_xor_channel.resource[0].start+XOR_MMAP_SIZE;
+
+	return;
+err4:
+	iounmap(xor_reg);
+err3:
+	iounmap(dma_reg1);
+err2:
+	iounmap(dma_reg0);
+err1:
+	iounmap(i2o_reg);
+	return;
+}
+
+static struct platform_device *ppc440spe_devs[] __initdata = {
+	&ppc440spe_dma_0_channel,
+	&ppc440spe_dma_1_channel,
+	&ppc440spe_xor_channel,
+};
+
+static int __init ppc440spe_register_raid_devices(void)
+{
+	ppc440spe_configure_raid_devices();
+	platform_add_devices(ppc440spe_devs, ARRAY_SIZE(ppc440spe_devs));
+
+	return 0;
+}
+
+arch_initcall(ppc440spe_register_raid_devices);
+#endif	/* CONFIG_AMCC_PPC440SPE_ADMA */
diff --git a/arch/ppc/platforms/4xx/ppc440spe.h b/arch/ppc/platforms/4xx/ppc440spe.h
index f1e867c..408e7c6 100644
--- a/arch/ppc/platforms/4xx/ppc440spe.h
+++ b/arch/ppc/platforms/4xx/ppc440spe.h
@@ -17,7 +17,6 @@
 #ifndef __PPC_PLATFORMS_PPC440SPE_H
 #define __PPC_PLATFORMS_PPC440SPE_H
 
-
 #include <asm/ibm44x.h>
 
 /* UART */
@@ -28,23 +27,28 @@
 #define UART1_INT		1
 #define UART2_INT		37
 
+/* GPIO macro register defines */
+#define GPIO_BASE		0x00000004f0000700ULL
+#define GPIO0_OR_OFFS		0x0
+#define GPIO0_IR_OFFS		0x1C
+
 /* Clock and Power Management */
 #define IBM_CPM_IIC0		0x80000000	/* IIC interface */
 #define IBM_CPM_IIC1		0x40000000	/* IIC interface */
 #define IBM_CPM_PCI		0x20000000	/* PCI bridge */
-#define IBM_CPM_CPU		    0x02000000	/* processor core */
-#define IBM_CPM_DMA		    0x01000000	/* DMA controller */
-#define IBM_CPM_BGO		    0x00800000	/* PLB to OPB bus arbiter */
-#define IBM_CPM_BGI		    0x00400000	/* OPB to PLB bridge */
-#define IBM_CPM_EBC		    0x00200000	/* External Bux Controller */
-#define IBM_CPM_EBM		    0x00100000	/* Ext Bus Master Interface */
-#define IBM_CPM_DMC		    0x00080000	/* SDRAM peripheral controller */
-#define IBM_CPM_PLB		    0x00040000	/* PLB bus arbiter */
+#define IBM_CPM_CPU		0x02000000	/* processor core */
+#define IBM_CPM_DMA		0x01000000	/* DMA controller */
+#define IBM_CPM_BGO		0x00800000	/* PLB to OPB bus arbiter */
+#define IBM_CPM_BGI		0x00400000	/* OPB to PLB bridge */
+#define IBM_CPM_EBC		0x00200000	/* External Bux Controller */
+#define IBM_CPM_EBM		0x00100000	/* Ext Bus Master Interface */
+#define IBM_CPM_DMC		0x00080000	/* SDRAM peripheral controller */
+#define IBM_CPM_PLB		0x00040000	/* PLB bus arbiter */
 #define IBM_CPM_SRAM		0x00020000	/* SRAM memory controller */
-#define IBM_CPM_PPM		    0x00002000	/* PLB Performance Monitor */
+#define IBM_CPM_PPM		0x00002000	/* PLB Performance Monitor */
 #define IBM_CPM_UIC1		0x00001000	/* Universal Interrupt Controller */
 #define IBM_CPM_GPIO0		0x00000800	/* General Purpose IO (??) */
-#define IBM_CPM_GPT		    0x00000400	/* General Purpose Timers  */
+#define IBM_CPM_GPT		0x00000400	/* General Purpose Timers  */
 #define IBM_CPM_UART0		0x00000200	/* serial port 0 */
 #define IBM_CPM_UART1		0x00000100	/* serial port 1 */
 #define IBM_CPM_UART2		0x00000100	/* serial port 1 */
@@ -59,5 +63,6 @@
 				| IBM_CPM_TAHOE0 | IBM_CPM_TAHOE1 \
 				| IBM_CPM_EMAC0 | IBM_CPM_EMAC1 \
 			  	| IBM_CPM_EMAC2 | IBM_CPM_EMAC3 )
-#endif /* __PPC_PLATFORMS_PPC440SP_H */
+
+#endif /* __PPC_PLATFORMS_PPC440SPE_H */
 #endif /* __KERNEL__ */
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
index 0991111..333f51a 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -28,7 +28,6 @@ endif
 endif
 obj-$(CONFIG_44x)		+= ppc4xx_pic.o
 obj-$(CONFIG_40x)		+= ppc4xx_setup.o
-obj-$(CONFIG_GEN_RTC)		+= todc_time.o
 obj-$(CONFIG_PPC4xx_DMA)	+= ppc4xx_dma.o
 obj-$(CONFIG_PPC4xx_EDMA)	+= ppc4xx_sgdma.o
 ifeq ($(CONFIG_40x),y)
@@ -48,9 +47,9 @@ obj-$(CONFIG_CHESTNUT)		+= mv64360_pic.o pci_auto.o
 obj-$(CONFIG_GT64260)		+= gt64260_pic.o
 obj-$(CONFIG_LOPEC)		+= pci_auto.o todc_time.o
 obj-$(CONFIG_HDPU)		+= pci_auto.o
-obj-$(CONFIG_LUAN)		+= pci_auto.o todc_time.o
-obj-$(CONFIG_YUCCA)		+= pci_auto.o todc_time.o
 obj-$(CONFIG_KATANA)		+= pci_auto.o
+obj-$(CONFIG_KATMAI)		+= pci_auto.o
+obj-$(CONFIG_LUAN)		+= pci_auto.o todc_time.o
 obj-$(CONFIG_MV64360)		+= mv64360_pic.o
 obj-$(CONFIG_MV64X60)		+= mv64x60.o mv64x60_win.o
 obj-$(CONFIG_MVME5100)		+= open_pic.o todc_time.o \
@@ -70,6 +69,7 @@ obj-$(CONFIG_SBC82xx)		+= todc_time.o
 obj-$(CONFIG_SPRUCE)		+= cpc700_pic.o pci_auto.o \
 				   todc_time.o
 obj-$(CONFIG_TAISHAN)		+= pci_auto.o
+obj-$(CONFIG_YUCCA)		+= pci_auto.o todc_time.o
 obj-$(CONFIG_8260)		+= m8260_setup.o pq2_devices.o pq2_sys.o \
 				   ppc_sys.o
 obj-$(CONFIG_PCI_8260)		+= m82xx_pci.o pci_auto.o
diff --git a/arch/ppc/syslib/ppc440spe_pcie.c b/arch/ppc/syslib/ppc440spe_pcie.c
index dd5d4b9..2aa0486 100644
--- a/arch/ppc/syslib/ppc440spe_pcie.c
+++ b/arch/ppc/syslib/ppc440spe_pcie.c
@@ -24,9 +24,19 @@ pcie_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
 		     int len, u32 *val)
 {
 	struct pci_controller *hose = bus->sysdata;
-
-	if (PCI_SLOT(devfn) != 1)
+#ifdef CONFIG_PCIE_ENDPOINT
+	/*
+	 * Endpoint can not generate upstream(remote) config cycles.
+	 */
+	return PCIBIOS_DEVICE_NOT_FOUND;
+#endif
+	if (!((PCI_SLOT(devfn) == 1) && (PCI_FUNC(devfn) == 0)))
 		return PCIBIOS_DEVICE_NOT_FOUND;
+	/*
+	 * 440SPE rev B implements only one function per port
+	 */
+	if (ppc440spe_revB())
+		devfn = 0;
 
 	offset += devfn << 12;
 
@@ -45,9 +55,6 @@ pcie_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
 		*val = in_le32(hose->cfg_data + offset);
 		break;
 	}
-
-	if (0) printk("%s: read %x(%d) @ %x\n", __func__, *val, len, offset);
-
 	return PCIBIOS_SUCCESSFUL;
 }
 
@@ -56,9 +63,20 @@ pcie_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
 		      int len, u32 val)
 {
 	struct pci_controller *hose = bus->sysdata;
+#ifdef CONFIG_PCIE_ENDPOINT
+	/*
+	 * Endpoint can not generate upstream(remote) config cycles.
+	 */
+	return PCIBIOS_DEVICE_NOT_FOUND;
+#endif
 
-	if (PCI_SLOT(devfn) != 1)
+	if (!((PCI_SLOT(devfn) == 1) && (PCI_FUNC(devfn) == 0)))
 		return PCIBIOS_DEVICE_NOT_FOUND;
+	/*
+	 * 440SPE rev B implements only one function per port
+	 */
+	if (ppc440spe_revB())
+		devfn = 0;
 
 	offset += devfn << 12;
 
@@ -92,13 +110,80 @@ enum {
 	LNKW_X8			= 0x8
 };
 
-static void check_error(void)
+int
+ppc440spe_revB(void)
+{
+	if (mfspr(SPRN_PVR) == 0x53421891)
+		return 1;
+	else
+		return 0;
+}
+
+/*
+ * Set up UTL registers
+ */
+static void
+ppc440spe_setup_utl(u32 port)
+{
+	void __iomem *utl_base;
+
+	/*
+	 * Map UTL at 0xc_1000_n000
+	 */
+	switch (port) {
+	case 0:
+		mtdcr(DCRN_PEGPL_REGBAH(PCIE0), 0x0000000c);
+		mtdcr(DCRN_PEGPL_REGBAL(PCIE0), 0x10000000);
+		mtdcr(DCRN_PEGPL_REGMSK(PCIE0), 0x00007001);
+		mtdcr(DCRN_PEGPL_SPECIAL(PCIE0), 0x68782800);
+		break;
+
+	case 1:
+		mtdcr(DCRN_PEGPL_REGBAH(PCIE1), 0x0000000c);
+		mtdcr(DCRN_PEGPL_REGBAL(PCIE1), 0x10001000);
+		mtdcr(DCRN_PEGPL_REGMSK(PCIE1), 0x00007001);
+		mtdcr(DCRN_PEGPL_SPECIAL(PCIE1), 0x68782800);
+		break;
+
+	case 2:
+		mtdcr(DCRN_PEGPL_REGBAH(PCIE2), 0x0000000c);
+		mtdcr(DCRN_PEGPL_REGBAL(PCIE2), 0x10002000);
+		mtdcr(DCRN_PEGPL_REGMSK(PCIE2), 0x00007001);
+		mtdcr(DCRN_PEGPL_SPECIAL(PCIE2), 0x68782800);
+		break;
+	}
+	utl_base = ioremap64(0xc10000000ull + 0x1000 * port, 0x100);
+	
+	/*
+	 * Set buffer allocations and then assert VRB and TXE.
+	 */
+	out_be32(utl_base + PEUTL_OUTTR,   0x08000000);
+	out_be32(utl_base + PEUTL_INTR,    0x02000000);
+	out_be32(utl_base + PEUTL_OPDBSZ,  0x10000000);
+	out_be32(utl_base + PEUTL_PBBSZ,   0x53000000);
+	out_be32(utl_base + PEUTL_IPHBSZ,  0x08000000);
+	out_be32(utl_base + PEUTL_IPDBSZ,  0x10000000);
+	out_be32(utl_base + PEUTL_RCIRQEN, 0x00f00000);
+	out_be32(utl_base + PEUTL_PCTL,    0x80800066);
+
+	iounmap(utl_base);
+}
+
+static int check_error(void)
 {
 	u32 valPE0, valPE1, valPE2;
+	int err = 0;
 
 	/* SDR0_PEGPLLLCT1 reset */
 	if (!(valPE0 = SDR_READ(PESDR0_PLLLCT1) & 0x01000000)) {
-		printk(KERN_INFO "PCIE: SDR0_PEGPLLLCT1 reset error 0x%8x\n", valPE0);
+		/*
+		 * the PCIe core was probably already initialised
+		 * by firmware - let's re-reset RCSSET regs
+		 */
+		pr_debug("PCIE: SDR0_PLLLCT1 already reset.\n");
+		SDR_WRITE(PESDR0_RCSSET, 0x01010000);
+		SDR_WRITE(PESDR1_RCSSET, 0x01010000);
+		SDR_WRITE(PESDR2_RCSSET, 0x01010000);
 	}
 
 	valPE0 = SDR_READ(PESDR0_RCSSET);
@@ -110,6 +195,7 @@ static void check_error(void)
 	     !(valPE1 & 0x01000000) ||
 	     !(valPE2 & 0x01000000)) {
 		printk(KERN_INFO "PCIE:  SDR0_PExRCSSET rstgu error\n");
+		err = -1;
 	}
 
 	/* SDR0_PExRCSSET rstdl */
@@ -117,6 +203,7 @@ static void check_error(void)
 	     !(valPE1 & 0x00010000) ||
 	     !(valPE2 & 0x00010000)) {
 		printk(KERN_INFO "PCIE:  SDR0_PExRCSSET rstdl error\n");
+		err = -1;
 	}
 
 	/* SDR0_PExRCSSET rstpyn */
@@ -124,6 +211,7 @@ static void check_error(void)
 	     (valPE1 & 0x00001000) ||
 	     (valPE2 & 0x00001000)) {
 		printk(KERN_INFO "PCIE:  SDR0_PExRCSSET rstpyn error\n");
+		err = -1;
 	}
 
 	/* SDR0_PExRCSSET hldplb */
@@ -131,6 +219,7 @@ static void check_error(void)
 	     (valPE1 & 0x10000000) ||
 	     (valPE2 & 0x10000000)) {
 		printk(KERN_INFO "PCIE:  SDR0_PExRCSSET hldplb error\n");
+		err = -1;
 	}
 
 	/* SDR0_PExRCSSET rdy */
@@ -138,6 +227,7 @@ static void check_error(void)
 	     (valPE1 & 0x00100000) ||
 	     (valPE2 & 0x00100000)) {
 		printk(KERN_INFO "PCIE:  SDR0_PExRCSSET rdy error\n");
+		err = -1;
 	}
 
 	/* SDR0_PExRCSSET shutdown */
@@ -145,44 +235,93 @@ static void check_error(void)
 	     (valPE1 & 0x00000100) ||
 	     (valPE2 & 0x00000100)) {
 		printk(KERN_INFO "PCIE:  SDR0_PExRCSSET shutdown error\n");
+		err = -1;
 	}
+	return err;
 }
 
 /*
- * Initialize PCI Express core as described in User Manual section 27.12.1
+ * Initialize PCI Express core as described in User Manual
  */
-int ppc440spe_init_pcie(void)
+static int
+ppc440spe_init_pcie(void)
 {
+	int time_out = 20;
+
 	/* Set PLL clock receiver to LVPECL */
 	SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) | 1 << 28);
 
-	check_error();
+	if (check_error())
+		return -1;
 
-	printk(KERN_INFO "PCIE initialization OK\n");
-
-	if (!(SDR_READ(PESDR0_PLLLCT2) & 0x10000))
-		printk(KERN_INFO "PESDR_PLLCT2 resistance calibration failed (0x%08x)\n",
+	if (!(SDR_READ(PESDR0_PLLLCT2) & 0x10000)) {
+		printk(KERN_INFO "PCIE: PESDR_PLLCT2 resistance calibration "
+				"failed (0x%08x)\n",
 		       SDR_READ(PESDR0_PLLLCT2));
+		return -1;
+	}
 
 	/* De-assert reset of PCIe PLL, wait for lock */
 	SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) & ~(1 << 24));
 	udelay(3);
 
+	while(time_out) {
+		if (!(SDR_READ(PESDR0_PLLLCT3) & 0x10000000)) {
+			time_out--;
+			udelay(1);
+		} else
+			break;
+	}
+	if (!time_out) {
+		printk(KERN_INFO "PCIE: VCO output not locked\n");
+		return -1;
+	}
+	
+	pr_debug("PCIE initialization OK\n");
+
 	return 0;
 }
 
-int ppc440spe_init_pcie_rootport(int port)
+/*
+ *  Yucca board as End point and root point setup
+ *                    and
+ *    testing inbound and out bound windows
+ *
+ *  YUCCA board can be plugged into another yucca board or you can get PCI-E
+ *  cable which can be used to setup loop back from one port to another port.
+ *  Please rememeber that unless there is a endpoint plugged in to root port it
+ *  will not initialize. It is the same in case of endpoint , unless there is
+ *  root port attached it will not initialize.
+ *
+ *  In this release of software all the PCI-E ports are configured as either
+ *  endpoint or rootpoint.In future we will have support for selective ports
+ *  setup as endpoint and root point in single board.
+ *
+ *  Once your board came up as root point , you can verify by reading
+ *  /proc/bus/pci/devices. Where you can see the configuration registers
+ *  of end point device attached to the port.
+ *
+ *  Enpoint cofiguration can be verified by connecting Yucca board to any
+ *  host or another yucca board. Then try to scan the device. In case of
+ *  linux use "lspci" or appripriate os command.
+ *  
+ *  To verify the inbound and outbound windows on yucca to yucca configuration
+ *  windows already configured for memory region 0. On root point side memory
+ *  map the 36 bit address value 0x4 0000 0000(SRAM) then do the read write to
+ *  the memory mapped address. On endpoint board memory map the 0x4 0000 0000
+ *  read the data to verify if writes happened or not.For inbound window 
+ *  verificatio do the reverse way of write and read .
+ */
+int ppc440spe_init_pcie_root_or_endport(u32 port)
 {
 	static int core_init;
-	void __iomem *utl_base;
+	int attempts;
 	u32 val = 0;
-	int i;
 
 	if (!core_init) {
+		if(ppc440spe_init_pcie())
+			return -1;
 		++core_init;
-		i = ppc440spe_init_pcie();
-		if (i)
-			return i;
 	}
 
 	/*
@@ -193,14 +332,25 @@ int ppc440spe_init_pcie_rootport(int port)
 	 * - Set up UTL configuration.
 	 * - Increase SERDES drive strength to levels suggested by AMCC.
 	 * - De-assert RSTPYN, RSTDL and RSTGU.
+	 *
+	 * NOTICE for revB chip: PESDRn_UTLSET2 is not set - we leave it with
+	 * default setting 0x11310000. The register has new fields,
+	 * PESDRn_UTLSET2[LKINE] in particular: clearing it leads to PCIE core
+	 * hang.
 	 */
+
+#ifdef CONFIG_PCIE_ENDPOINT
+#define PTYPE_TYPE PTYPE_LEGACY_ENDPOINT
+#else
+#define PTYPE_TYPE PTYPE_ROOT_PORT
+#endif
 	switch (port) {
 	case 0:
-		SDR_WRITE(PESDR0_DLPSET, PTYPE_ROOT_PORT << 20 | LNKW_X8 << 12);
-
-		SDR_WRITE(PESDR0_UTLSET1, 0x21222222);
-		SDR_WRITE(PESDR0_UTLSET2, 0x11000000);
+		SDR_WRITE(PESDR0_DLPSET, 1 << 24 | PTYPE_TYPE << 20 | LNKW_X8 << 12); 
 
+		SDR_WRITE(PESDR0_UTLSET1, 0x20222222);
+		if (!ppc440spe_revB())
+			SDR_WRITE(PESDR0_UTLSET2, 0x11000000);
 		SDR_WRITE(PESDR0_HSSL0SET1, 0x35000000);
 		SDR_WRITE(PESDR0_HSSL1SET1, 0x35000000);
 		SDR_WRITE(PESDR0_HSSL2SET1, 0x35000000);
@@ -215,11 +365,11 @@ int ppc440spe_init_pcie_rootport(int port)
 		break;
 
 	case 1:
-		SDR_WRITE(PESDR1_DLPSET, PTYPE_ROOT_PORT << 20 | LNKW_X4 << 12);
-
-		SDR_WRITE(PESDR1_UTLSET1, 0x21222222);
-		SDR_WRITE(PESDR1_UTLSET2, 0x11000000);
+		SDR_WRITE(PESDR1_DLPSET, 1 << 24 | PTYPE_TYPE << 20 | LNKW_X4 << 12); 
 
+		SDR_WRITE(PESDR1_UTLSET1, 0x20222222);
+		if (!ppc440spe_revB())
+			SDR_WRITE(PESDR1_UTLSET2, 0x11000000);
 		SDR_WRITE(PESDR1_HSSL0SET1, 0x35000000);
 		SDR_WRITE(PESDR1_HSSL1SET1, 0x35000000);
 		SDR_WRITE(PESDR1_HSSL2SET1, 0x35000000);
@@ -230,11 +380,11 @@ int ppc440spe_init_pcie_rootport(int port)
 		break;
 
 	case 2:
-		SDR_WRITE(PESDR2_DLPSET, PTYPE_ROOT_PORT << 20 | LNKW_X4 << 12);
-
-		SDR_WRITE(PESDR2_UTLSET1, 0x21222222);
-		SDR_WRITE(PESDR2_UTLSET2, 0x11000000);
+		SDR_WRITE(PESDR2_DLPSET, 1 << 24 | PTYPE_TYPE << 20 | LNKW_X4 << 12); 
 
+		SDR_WRITE(PESDR2_UTLSET1, 0x20222222);
+		if (!ppc440spe_revB())
+			SDR_WRITE(PESDR2_UTLSET2, 0x11000000);
 		SDR_WRITE(PESDR2_HSSL0SET1, 0x35000000);
 		SDR_WRITE(PESDR2_HSSL1SET1, 0x35000000);
 		SDR_WRITE(PESDR2_HSSL2SET1, 0x35000000);
@@ -244,89 +394,107 @@ int ppc440spe_init_pcie_rootport(int port)
 			  (SDR_READ(PESDR2_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);
 		break;
 	}
-
 	mdelay(1000);
 
 	switch (port) {
-	case 0: val = SDR_READ(PESDR0_RCSSTS); break;
-	case 1: val = SDR_READ(PESDR1_RCSSTS); break;
-	case 2: val = SDR_READ(PESDR2_RCSSTS); break;
+	case 0:
+		val = SDR_READ(PESDR0_RCSSTS);
+		break;
+		
+	case 1:
+		val = SDR_READ(PESDR1_RCSSTS);
+		break;
+		
+	case 2:
+		val = SDR_READ(PESDR2_RCSSTS);
+		break;
 	}
 
-	if (!(val & (1 << 20)))
-		printk(KERN_INFO "PCIE%d: PGRST inactive\n", port);
-	else
-		printk(KERN_WARNING "PGRST for PCIE%d failed %08x\n", port, val);
-
-	switch (port) {
-	case 0: printk(KERN_INFO "PCIE0: LOOP %08x\n", SDR_READ(PESDR0_LOOP)); break;
-	case 1: printk(KERN_INFO "PCIE1: LOOP %08x\n", SDR_READ(PESDR1_LOOP)); break;
-	case 2: printk(KERN_INFO "PCIE2: LOOP %08x\n", SDR_READ(PESDR2_LOOP)); break;
+	if (val & (1 << 20)) {
+		printk(KERN_WARNING "PGRST for PCIE%d failed %08x\n",
+				port, val);
+		return -1;
 	}
 
 	/*
-	 * Map UTL registers at 0xc_1000_0n00
+	 * Verify link is up
 	 */
+	val = 0;
 	switch (port) {
 	case 0:
-		mtdcr(DCRN_PEGPL_REGBAH(PCIE0), 0x0000000c);
-		mtdcr(DCRN_PEGPL_REGBAL(PCIE0), 0x10000000);
-		mtdcr(DCRN_PEGPL_REGMSK(PCIE0), 0x00007001);
-		mtdcr(DCRN_PEGPL_SPECIAL(PCIE0), 0x68782800);
+		val = SDR_READ(PESDR0_LOOP);
 		break;
-
 	case 1:
-		mtdcr(DCRN_PEGPL_REGBAH(PCIE1), 0x0000000c);
-		mtdcr(DCRN_PEGPL_REGBAL(PCIE1), 0x10001000);
-		mtdcr(DCRN_PEGPL_REGMSK(PCIE1), 0x00007001);
-		mtdcr(DCRN_PEGPL_SPECIAL(PCIE1), 0x68782800);
+		val = SDR_READ(PESDR1_LOOP);
 		break;
-
 	case 2:
-		mtdcr(DCRN_PEGPL_REGBAH(PCIE2), 0x0000000c);
-		mtdcr(DCRN_PEGPL_REGBAL(PCIE2), 0x10002000);
-		mtdcr(DCRN_PEGPL_REGMSK(PCIE2), 0x00007001);
-		mtdcr(DCRN_PEGPL_SPECIAL(PCIE2), 0x68782800);
+		val = SDR_READ(PESDR2_LOOP);
+		break;
+	}
+	if (!(val & 0x00001000)) {
+		printk(KERN_INFO "PCIE: link is not up for port %d.\n", port);
+		return -1;
 	}
-
-	utl_base = ioremap64(0xc10000000ull + 0x1000 * port, 0x100);
 
 	/*
-	 * Set buffer allocations and then assert VRB and TXE.
+	 * Setup UTL registers - but only on revA!
+	 * We use default settings for revB chip.
 	 */
-	out_be32(utl_base + PEUTL_OUTTR,   0x08000000);
-	out_be32(utl_base + PEUTL_INTR,    0x02000000);
-	out_be32(utl_base + PEUTL_OPDBSZ,  0x10000000);
-	out_be32(utl_base + PEUTL_PBBSZ,   0x53000000);
-	out_be32(utl_base + PEUTL_IPHBSZ,  0x08000000);
-	out_be32(utl_base + PEUTL_IPDBSZ,  0x10000000);
-	out_be32(utl_base + PEUTL_RCIRQEN, 0x00f00000);
-	out_be32(utl_base + PEUTL_PCTL,    0x80800066);
-
-	iounmap(utl_base);
+	if (!ppc440spe_revB())
+		ppc440spe_setup_utl(port);
 
 	/*
-	 * We map PCI Express configuration access into the 512MB regions
+	 * We map PCI Express configuration access into the 512MB regions.
+	 *
+	 * NOTICE: revB is very strict about PLB real addressess and ranges to
+	 * be mapped for config space; it seems to only work with d_nnnn_nnnn
+	 * range (hangs the core upon config transaction attempts when set
+	 * otherwise) while revA uses c_nnnn_nnnn.
+	 *
+	 * For revA:
 	 *     PCIE0: 0xc_4000_0000
 	 *     PCIE1: 0xc_8000_0000
 	 *     PCIE2: 0xc_c000_0000
+	 *
+	 * For revB:
+	 *     PCIE0: 0xd_0000_0000
+	 *     PCIE1: 0xd_2000_0000
+	 *     PCIE2: 0xd_4000_0000
 	 */
 	switch (port) {
 	case 0:
-		mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000c);
-		mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x40000000);
+		if (ppc440spe_revB()) {
+			mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000d);
+			mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x00000000);
+		} else {
+			/* revA */
+			mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000c);
+			mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x40000000);
+		}
 		mtdcr(DCRN_PEGPL_CFGMSK(PCIE0), 0xe0000001); /* 512MB region, valid */
 		break;
 
 	case 1:
-		mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000c);
-		mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x80000000);
+		if (ppc440spe_revB()) {
+			mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000d);
+			mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x20000000);
+		} else {
+			/* revA */
+			mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000c);
+			mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x80000000);
+		}
 		mtdcr(DCRN_PEGPL_CFGMSK(PCIE1), 0xe0000001); /* 512MB region, valid */
 		break;
 
 	case 2:
-		mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000c);
-		mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0xc0000000);
+		if (ppc440spe_revB()) {
+			mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000d);
+			mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0x40000000);
+		} else {
+			/* revA */
+			mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000c);
+			mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0xc0000000);
+		}
 		mtdcr(DCRN_PEGPL_CFGMSK(PCIE2), 0xe0000001); /* 512MB region, valid */
 		break;
 	}
@@ -334,69 +502,100 @@ int ppc440spe_init_pcie_rootport(int port)
 	/*
 	 * Check for VC0 active and assert RDY.
 	 */
+	attempts = 10;
 	switch (port) {
 	case 0:
-		if (!(SDR_READ(PESDR0_RCSSTS) & (1 << 16)))
-			printk(KERN_WARNING "PCIE0: VC0 not active\n");
+		while(!(SDR_READ(PESDR0_RCSSTS) & (1 << 16))) {
+			if (!(attempts--)) {
+				printk(KERN_WARNING "PCIE0: VC0 not active\n");
+				return -1;
+			}
+			mdelay(1000);
+		}
 		SDR_WRITE(PESDR0_RCSSET, SDR_READ(PESDR0_RCSSET) | 1 << 20);
 		break;
 	case 1:
-		if (!(SDR_READ(PESDR1_RCSSTS) & (1 << 16)))
-			printk(KERN_WARNING "PCIE0: VC0 not active\n");
+		while(!(SDR_READ(PESDR1_RCSSTS) & (1 << 16))) {
+			if (!(attempts--)) {
+				printk(KERN_WARNING "PCIE1: VC0 not active\n");
+				return -1;
+			}
+			mdelay(1000);
+		}
+
 		SDR_WRITE(PESDR1_RCSSET, SDR_READ(PESDR1_RCSSET) | 1 << 20);
 		break;
 	case 2:
-		if (!(SDR_READ(PESDR2_RCSSTS) & (1 << 16)))
-			printk(KERN_WARNING "PCIE0: VC0 not active\n");
+		while(!(SDR_READ(PESDR2_RCSSTS) & (1 << 16))) {
+			if (!(attempts--)) {
+				printk(KERN_WARNING "PCIE2: VC0 not active\n");
+				return -1;
+			}
+			mdelay(1000);
+		}
+
 		SDR_WRITE(PESDR2_RCSSET, SDR_READ(PESDR2_RCSSET) | 1 << 20);
 		break;
 	}
 
-#if 0
-	/* Dump all config regs */
-	for (i = 0x300; i <= 0x320; ++i)
-		printk("[%04x] 0x%08x\n", i, SDR_READ(i));
-	for (i = 0x340; i <= 0x353; ++i)
-		printk("[%04x] 0x%08x\n", i, SDR_READ(i));
-	for (i = 0x370; i <= 0x383; ++i)
-		printk("[%04x] 0x%08x\n", i, SDR_READ(i));
-	for (i = 0x3a0; i <= 0x3a2; ++i)
-		printk("[%04x] 0x%08x\n", i, SDR_READ(i));
-	for (i = 0x3c0; i <= 0x3c3; ++i)
-		printk("[%04x] 0x%08x\n", i, SDR_READ(i));
-#endif
-
 	mdelay(100);
 
 	return 0;
 }
 
-void ppc440spe_setup_pcie(struct pci_controller *hose, int port)
+int ppc440spe_setup_pcie(struct pci_controller *hose, u32 port)
 {
 	void __iomem *mbase;
+	int attempts = 0;
+
+	if (ppc440spe_revB()) {
+		/*
+		 * NOTICE: revB is very strict about PLB real addressess and
+		 * sizes to be mapped for config space; it hangs the core upon
+		 * config transaction attempt if not set to 0xd_0010_0000,
+		 * 0xd_2010_0000, 0xd_4010_0000 respectively.
+		 */
+		hose->cfg_data = ioremap64(0xd00100000ull + port * 0x20000000,
+					0x400);
+
+		/* for accessing Local Config space we need to set A[35] */
+		mbase = ioremap64(0xd10000000ull + port * 0x20000000, 0x400);
+	} else {
+		/* revA */
+
+		/*
+		 * Map 16MB, which is enough for 4 bits of bus #
+		 */
+		hose->cfg_data = ioremap64(0xc40100000ull + port * 0x40000000,
+					0x01000000);
+		mbase = ioremap64(0xc50000000ull + port * 0x40000000, 0x1000);
+	}
 
-	/*
-	 * Map 16MB, which is enough for 4 bits of bus #
-	 */
-	hose->cfg_data = ioremap64(0xc40000000ull + port * 0x40000000,
-				   1 << 24);
 	hose->ops = &pcie_pci_ops;
 
+#ifndef CONFIG_PCIE_ENDPOINT
 	/*
 	 * Set bus numbers on our root port
 	 */
-	mbase = ioremap64(0xc50000000ull + port * 0x40000000, 4096);
-	out_8(mbase + PCI_PRIMARY_BUS, 0);
-	out_8(mbase + PCI_SECONDARY_BUS, 0);
-
+		out_8(mbase + PCI_PRIMARY_BUS, 0);
+		out_8(mbase + PCI_SECONDARY_BUS, 1);
+		out_8(mbase + PCI_SUBORDINATE_BUS, 1);
+#endif
 	/*
 	 * Set up outbound translation to hose->mem_space from PLB
 	 * addresses at an offset of 0xd_0000_0000.  We set the low
 	 * bits of the mask to 11 to turn off splitting into 8
 	 * subregions and to enable the outbound translation.
+	 * POMs are set different for root and endpoints to 
+	 * different window ranges fron inbound and out bound transactions.
 	 */
+#ifdef CONFIG_PCIE_ENDPOINT
+	out_le32(mbase + PECFG_POM0LAH, 0x0000fff8);
+	out_le32(mbase + PECFG_POM0LAL, 0x0001fff8);
+#else
 	out_le32(mbase + PECFG_POM0LAH, 0);
-	out_le32(mbase + PECFG_POM0LAL, hose->mem_space.start);
+	out_le32(mbase + PECFG_POM0LAL, hose->mem_space.start );
+#endif
 
 	switch (port) {
 	case 0:
@@ -404,38 +603,148 @@ void ppc440spe_setup_pcie(struct pci_controller *hose, int port)
 		mtdcr(DCRN_PEGPL_OMR1BAL(PCIE0),  hose->mem_space.start);
 		mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE0), 0x7fffffff);
 		mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE0),
-		      ~(hose->mem_space.end - hose->mem_space.start) | 3);
+		      ~(BOARD_PCIE_MEM_SIZE - 1) | 3);
 		break;
 	case 1:
 		mtdcr(DCRN_PEGPL_OMR1BAH(PCIE1),  0x0000000d);
 		mtdcr(DCRN_PEGPL_OMR1BAL(PCIE1),  hose->mem_space.start);
 		mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE1), 0x7fffffff);
 		mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE1),
-		      ~(hose->mem_space.end - hose->mem_space.start) | 3);
-
+		      ~(BOARD_PCIE_MEM_SIZE - 1) | 3);
 		break;
 	case 2:
 		mtdcr(DCRN_PEGPL_OMR1BAH(PCIE2),  0x0000000d);
 		mtdcr(DCRN_PEGPL_OMR1BAL(PCIE2),  hose->mem_space.start);
 		mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE2), 0x7fffffff);
 		mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE2),
-		      ~(hose->mem_space.end - hose->mem_space.start) | 3);
+		      ~(BOARD_PCIE_MEM_SIZE - 1) | 3);
 		break;
 	}
 
 	/* Set up 16GB inbound memory window at 0 */
-	out_le32(mbase + PCI_BASE_ADDRESS_0, 0);
-	out_le32(mbase + PCI_BASE_ADDRESS_1, 0);
+#ifndef CONFIG_PCIE_ENDPOINT
 	out_le32(mbase + PECFG_BAR0HMPA, 0x7fffffc);
 	out_le32(mbase + PECFG_BAR0LMPA, 0);
-	out_le32(mbase + PECFG_PIM0LAL, 0);
-	out_le32(mbase + PECFG_PIM0LAH, 0);
+#else
+	out_le32(mbase + PECFG_BAR0HMPA, 0xfffffffc);
+	out_le32(mbase + PECFG_BAR0LMPA, 0xffff0000);
+#endif
+	out_le32(mbase + PCI_BASE_ADDRESS_0, 0);
+	out_le32(mbase + PCI_BASE_ADDRESS_1, 0);
+
+	/*
+	 *  SRAM location 0x4 0000 0000 is target for inbound transefers
+	 */
+	out_le32(mbase + PECFG_PIM0LAL, 0x00000000);
+	out_le32(mbase + PECFG_PIM0LAH, 0x00000004);
+	out_le32(mbase + PECFG_PIM1LAL, 0x00000000);
+	out_le32(mbase + PECFG_PIM1LAH, 0x00000004);
+	out_le32(mbase + PECFG_PIM01SAH, 0xffff0000);
+	out_le32(mbase + PECFG_PIM01SAL, 0x00000000);
 	out_le32(mbase + PECFG_PIMEN, 0x1);
 
 	/* Enable I/O, Mem, and Busmaster cycles */
 	out_le16(mbase + PCI_COMMAND,
 		 in_le16(mbase + PCI_COMMAND) |
 		 PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+	attempts = 10;
+#ifndef CONFIG_PCIE_ENDPOINT
+	printk(KERN_INFO"PCIE:%d successfully set as rootpoint\n",port);
+	switch(port )
+	{
+		case 0:
+			out_le16(mbase + 0x200,0xaaa0);
+			out_le16(mbase + 0x202,0xbed0);
+			break;
+		case 1:
+			out_le16(mbase + 0x200,0xaaa1);
+			out_le16(mbase + 0x202,0xbed1);
+			break;
+		case 2:
+			out_le16(mbase + 0x200,0xaaa2);
+			out_le16(mbase + 0x202,0xbed2);
+			break;
+		default:
+			out_le16(mbase + 0x200,0xaaa3);
+			out_le16(mbase + 0x202,0xbed3);
+	}
+#else
+	switch (port) {
+	case 0:
+		while(!(SDR_READ(PESDR0_RCSSTS) & (1 << 8))) {
+			if (!(attempts--)) {
+				printk(KERN_INFO "PCIE0: BMEN is not active\n");
+				return -1;
+			}
+			mdelay(1000);
+		}
+		break;
+	case 1:
+		while(!(SDR_READ(PESDR1_RCSSTS) & (1 << 8))) {
+			if (!(attempts--)) {
+				printk(KERN_WARNING "PCIE1: BEMEN not active\n");
+				return -1;
+			}
+			mdelay(1000);
+		}
+		break;
+	case 2:
+		while(!(SDR_READ(PESDR2_RCSSTS) & (1 << 8))) {
+			if (!(attempts--)) {
+				printk(KERN_WARNING "PCIE2: BMEN is not active\n");
+				return -1;
+			}
+			mdelay(1000);
+		}
+		break;
+	}
+	printk(KERN_INFO"PCIE:%d successfully set as endpoint\n",port);
+	switch(port)
+	{
+		case 0:
+			out_le16(mbase + 0x200,0xeee0);
+			out_le16(mbase + 0x202,0xfed0);
+			break;
+		case 1:
+			out_le16(mbase + 0x200,0xeee1);
+			out_le16(mbase + 0x202,0xfed1);
+			break;
+		case 2:
+			out_le16(mbase + 0x200,0xeee2);
+			out_le16(mbase + 0x202,0xfed2);
+			break;
+		default :
+			out_le16(mbase + 0x200,0xeee3);
+			out_le16(mbase + 0x202,0xfed3);
+	}
+#endif
+	printk(KERN_INFO"vendor-id 0x%x\n",in_le16(mbase+0x0));
+	printk(KERN_INFO"device-id 0x%x\n",in_le16(mbase+0x2));
+	/*
+	 * This code works as is with yucca plugged in another yucca board or any endpoint device 
+	 * pugged in yucca board as root point device.
+	 * If you want to change configuration according to your configuration . Here are few gotch's.
+	 * There could be hangs due to different reasons
+	 * 1 -- It could be that endpoint is not initialyzed. So always initialize the endpoint first.
+	 * 2 -- May be your POM and BARs are not set properly
+	 * 3 -- careful with masks which decide window sizes
+	 * Here is the test code which used for testing sram read . This test dumps remote and local sram 
+	 * locations which help in comparing visually.
+	 * u32 *rsram,*lsram;
+	 * int i=0;
+	 * lsram = ioremap64(0x400000000 ,0x200); 
+     * #ifndef CONFIG_PCIE_ENDPOINT
+	 *    rsram = ioremap64(0xd00000000 + hose->mem_space.start,0x200);
+	 *	 if(port == 1)
+	 *		 for(i=0;i<20;i+=4) 
+	 *			 printk(KERN_INFO"endp sram 0x%x root sram 0x%x\n",*(rsram+i),*(lsram+i));
+     *#else
+	 *    rsram = ioremap64(0xd00000000 + hose->mem_space.start,0x200);
+	 *    for(i=0;i<20;i+=4) 
+	 *		 printk(KERN_INFO"rootp sram 0x%x endp sram 0x%x\n",*(rsram+i),*(lsram+i));
+     * #endif
+    */
 
 	iounmap(mbase);
+	return 0;
 }
diff --git a/arch/ppc/syslib/ppc440spe_pcie.h b/arch/ppc/syslib/ppc440spe_pcie.h
index 55b765a..e7099a3 100644
--- a/arch/ppc/syslib/ppc440spe_pcie.h
+++ b/arch/ppc/syslib/ppc440spe_pcie.h
@@ -13,6 +13,8 @@
 
 #define DCRN_SDR0_CFGADDR	0x00e
 #define DCRN_SDR0_CFGDATA	0x00f
+#define DCRN_I2O0_IBAL		0x066
+#define DCRN_I2O0_IBAH		0x067
 
 #define DCRN_PCIE0_BASE		0x100
 #define DCRN_PCIE1_BASE		0x120
@@ -136,14 +138,20 @@
  */
 #define PECFG_BAR0LMPA		0x210
 #define PECFG_BAR0HMPA		0x214
-#define PECFG_PIMEN		0x33c
+#define PECFG_BAR1MPA     	0x218
+#define PECFG_BAR2MPA     	0x220
+#define PECFG_PIMEN			0x33c
 #define PECFG_PIM0LAL		0x340
 #define PECFG_PIM0LAH		0x344
+#define PECFG_PIM1LAL       0x348
+#define PECFG_PIM1LAH       0x34c
+#define PECFG_PIM01SAL    	0x350
+#define PECFG_PIM01SAH      0x354
 #define PECFG_POM0LAL		0x380
 #define PECFG_POM0LAH		0x384
 
-int ppc440spe_init_pcie(void);
-int ppc440spe_init_pcie_rootport(int port);
-void ppc440spe_setup_pcie(struct pci_controller *hose, int port);
+int ppc440spe_revB(void);
+int ppc440spe_init_pcie_root_or_endport(u32 port);
+int ppc440spe_setup_pcie(struct pci_controller *hose, u32 port);
 
 #endif /* __PPC_SYSLIB_PPC440SPE_PCIE_H */
diff --git a/include/asm-ppc/ibm44x.h b/include/asm-ppc/ibm44x.h
index 7818b54..38f5959 100644
--- a/include/asm-ppc/ibm44x.h
+++ b/include/asm-ppc/ibm44x.h
@@ -85,7 +85,7 @@
  */
 #if defined(CONFIG_440SP) || defined(CONFIG_440SPE)
 #define PPC44x_IO_LO		0xf0000000UL
-#define PPC44x_IO_HI		0xf0000fffUL
+#define PPC44x_IO_HI		0xffffffffUL	/* used not only for PCI-IO but for EBC too */
 #define PPC44x_PCI0CFG_LO	0x0ec00000UL
 #define PPC44x_PCI0CFG_HI	0x0ec00007UL
 #define PPC44x_PCI1CFG_LO	0x1ec00000UL
@@ -556,12 +556,19 @@
 #define PCIX1_CFGD		0x1ec00004UL
 #define PCIX2_CFGD		0x2ec00004UL
 
+#if defined (CONFIG_440SPE)
+#define PCIX0_IO_BASE		0x0000000C08000000ULL
+#else
 #define PCIX0_IO_BASE		0x0000000908000000ULL
 #define PCIX1_IO_BASE		0x0000000908000000ULL
 #define PCIX2_IO_BASE		0x0000000908000000ULL
+#endif
+
 #define PCIX_IO_SIZE		0x00010000
 
-#ifdef CONFIG_440SP
+#if defined (CONFIG_440SPE)
+#define PCIX0_REG_BASE		0x0000000c0ec80000ULL
+#elif defined(CONFIG_440SP)
 #define PCIX0_REG_BASE		0x000000090ec80000ULL
 #else
 #define PCIX0_REG_BASE		0x000000020ec80000ULL